Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

21 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

hackathon-todo - Phase 2 Full-Stack Todo Application

A modern, secure, full-stack todo application built with Next.js, FastAPI, and PostgreSQL. This project implements a complete task management system with JWT-based authentication, responsive UI, and data isolation between users.

πŸš€ Features

  • βœ… Full CRUD Operations - Create, read, update, and delete tasks
  • πŸ” Secure Authentication - JWT-based authentication with Better Auth
  • πŸ‘₯ Multi-User Support - Complete data isolation between users
  • πŸ“± Responsive Design - Works seamlessly on mobile and desktop
  • ⚑ Optimistic UI - Instant feedback with automatic rollback on errors
  • 🎯 Task Management - Mark tasks as complete/incomplete, filter by status
  • πŸ₯ Health Checks - Database connection monitoring endpoint
  • β™Ώ Accessible - ARIA labels and keyboard navigation support

πŸ“‹ Table of Contents

πŸ›  Tech Stack

Frontend

  • Framework: Next.js 16+ (App Router)
  • Language: TypeScript
  • Styling: TailwindCSS
  • Authentication: Better Auth (JWT plugin)
  • UI Components: Custom responsive components

Backend

  • Framework: FastAPI
  • Language: Python 3.13+
  • ORM: SQLModel
  • Database: Neon Serverless PostgreSQL
  • Authentication: JWT validation with python-jose
  • Server: Uvicorn

Development Tools

  • Package Manager:
    • Frontend: npm
    • Backend: UV (Python package manager)
  • Version Control: Git

πŸ“ Project Structure

hackathon-todo/
β”œβ”€β”€ frontend/               # Next.js application
β”‚   β”œβ”€β”€ app/               # App Router pages and layouts
β”‚   β”‚   β”œβ”€β”€ (auth)/        # Authentication pages (signin, signup)
β”‚   β”‚   β”œβ”€β”€ (dashboard)/   # Protected dashboard pages
β”‚   β”‚   └── page.tsx       # Landing page
β”‚   β”œβ”€β”€ components/        # Reusable UI components
β”‚   β”‚   β”œβ”€β”€ Navbar.tsx
β”‚   β”‚   β”œβ”€β”€ TaskForm.tsx
β”‚   β”‚   β”œβ”€β”€ TaskItem.tsx
β”‚   β”‚   └── TaskList.tsx
β”‚   β”œβ”€β”€ lib/              # Utilities and configurations
β”‚   β”‚   β”œβ”€β”€ api.ts        # API client with JWT
β”‚   β”‚   β”œβ”€β”€ auth.ts       # Server-side auth config
β”‚   β”‚   β”œβ”€β”€ auth-client.ts # Client-side auth hooks
β”‚   β”‚   └── types.ts      # TypeScript interfaces
β”‚   └── package.json
β”‚
β”œβ”€β”€ backend/              # FastAPI application
β”‚   β”œβ”€β”€ main.py          # App initialization and health checks
β”‚   β”œβ”€β”€ config.py        # Environment configuration
β”‚   β”œβ”€β”€ db.py            # Database engine and session
β”‚   β”œβ”€β”€ models.py        # SQLModel task model
β”‚   β”œβ”€β”€ schemas.py       # Pydantic request/response schemas
β”‚   β”œβ”€β”€ middleware.py    # JWT authentication middleware
β”‚   β”œβ”€β”€ routes/          # API route handlers
β”‚   β”‚   └── tasks.py     # Task CRUD endpoints
β”‚   β”œβ”€β”€ migrations/      # Database migrations
β”‚   β”‚   └── 001_create_tasks_table.sql
β”‚   β”œβ”€β”€ scripts/         # Utility scripts
β”‚   β”‚   └── migrate.py   # Migration runner
β”‚   └── pyproject.toml
β”‚
└── specs/               # Feature specifications
    β”œβ”€β”€ overview.md
    β”œβ”€β”€ architecture.md
    └── 001-phase2-implementation/
        β”œβ”€β”€ spec.md
        β”œβ”€β”€ plan.md
        β”œβ”€β”€ tasks.md
        └── data-model.md

🏁 Quick Start

Prerequisites

  • Node.js 18+ and npm
  • Python 3.13+
  • UV Python package manager (installation guide)
  • Neon PostgreSQL account and database (sign up)

1. Clone the Repository

git clone <repository-url>
cd hackathon-todo

2. Set Up Frontend

cd frontend

# Install dependencies
npm install

# Create environment file
cp .env.local.example .env.local

# Edit .env.local with your configuration:
# - NEXT_PUBLIC_API_URL=http://localhost:8000
# - BETTER_AUTH_SECRET=<your-secret-key>
# - DATABASE_URL=<your-neon-postgres-url>
# - BETTER_AUTH_URL=http://localhost:3000

# Start development server
npm run dev

The frontend will be available at http://localhost:3000

3. Set Up Backend

cd backend

# Install dependencies using UV
uv pip install -e .

# Create environment file
cp .env.example .env

# Edit .env with your configuration:
# - DATABASE_URL=<your-neon-postgres-url>
# - BETTER_AUTH_SECRET=<same-secret-as-frontend>
# - API_HOST=0.0.0.0
# - API_PORT=8000

# Run database migrations
python scripts/migrate.py

# Start development server
uvicorn main:app --reload --host 0.0.0.0 --port 8000

The backend will be available at http://localhost:8000

API documentation (Swagger UI): http://localhost:8000/docs

πŸ” Environment Variables

Frontend (.env.local)

# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:8000

# Better Auth Configuration
BETTER_AUTH_SECRET=your-secret-key-min-32-chars
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=postgresql://user:password@host/database

# Next.js Configuration (optional)
NEXT_PUBLIC_APP_URL=http://localhost:3000

Backend (.env)

# Database Configuration
DATABASE_URL=postgresql://user:password@host/database

# Authentication
BETTER_AUTH_SECRET=your-secret-key-min-32-chars

# Server Configuration
API_HOST=0.0.0.0
API_PORT=8000
ENVIRONMENT=development

Important: Use the same BETTER_AUTH_SECRET in both frontend and backend for JWT validation to work correctly.

πŸ’» Development

Frontend Development

cd frontend

# Start dev server
npm run dev

# Build for production
npm run build

# Run linter
npm run lint

# Format code
npm run format

Backend Development

cd backend

# Start dev server with auto-reload
uvicorn main:app --reload

# Run with custom host/port
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

# Run migrations
python scripts/migrate.py

Database Migrations

Migrations are located in backend/migrations/. To create a new migration:

  1. Create a new SQL file: backend/migrations/00X_description.sql
  2. Write your migration SQL
  3. Run: python backend/scripts/migrate.py

πŸ“š API Documentation

Authentication Flow

  1. Sign Up: POST /api/auth/signup (handled by Better Auth)
  2. Sign In: POST /api/auth/signin (handled by Better Auth)
  3. Get Session: GET /api/auth/session (handled by Better Auth)

Better Auth automatically handles user registration, login, and JWT token generation.

Task Endpoints

All task endpoints require JWT authentication via Authorization: Bearer <token> header.

List Tasks

GET /api/{user_id}/tasks?status=all

Query parameters:

  • status: all | pending | completed (default: all)

Create Task

POST /api/{user_id}/tasks
Content-Type: application/json

{
  "title": "Buy groceries",
  "description": "Milk, eggs, bread"
}

Get Single Task

GET /api/{user_id}/tasks/{task_id}

Update Task

PUT /api/{user_id}/tasks/{task_id}
Content-Type: application/json

{
  "title": "Updated title",
  "description": "Updated description"
}

Toggle Completion

PATCH /api/{user_id}/tasks/{task_id}/complete

Delete Task

DELETE /api/{user_id}/tasks/{task_id}

Health Check

GET /api/health

Returns database connection status and environment info.

πŸ§ͺ Testing

Frontend Testing

cd frontend
npm test

Backend Testing

Comprehensive testing procedures are documented in backend/TESTING.md.

Manual Testing

  1. Concurrent Operations (T089):

    • Open multiple browser tabs
    • Perform simultaneous create/update/delete operations
    • Verify data consistency
  2. Data Isolation (T090):

    • Create two user accounts
    • Verify User A cannot access User B's tasks
    • Test all CRUD operations across users
  3. Performance Testing:

    • Measure API response times (target: < 500ms p95)
    • Test frontend load time (target: < 2 seconds)

See backend/TESTING.md for detailed test procedures.

πŸš€ Deployment

Frontend Deployment (Vercel)

cd frontend
npm run build
# Deploy to Vercel or your preferred hosting platform

Environment variables must be set in your deployment platform.

Backend Deployment

The backend can be deployed to:

  • Heroku: Add Procfile with web: uvicorn main:app --host 0.0.0.0 --port $PORT
  • Railway: Configure start command in railway.toml
  • Docker: Use provided Dockerfile (if available)
  • AWS/GCP: Deploy as containerized application

Ensure DATABASE_URL points to your production Neon database.

πŸ— Architecture

Request Flow

User β†’ Next.js β†’ Better Auth β†’ JWT β†’ FastAPI β†’ SQLModel β†’ Neon DB
         ↑                        ↓          ↓
    Authorization Header   Verify Token   Filter by user_id

Key Design Decisions

  1. Stateless Backend: No session storage; all authentication via JWT
  2. JWT-Based Auth: Shared secret between frontend and backend
  3. User Isolation: All database queries filtered by user_id from JWT
  4. Optimistic UI: Immediate feedback with automatic rollback on errors
  5. Responsive Design: Mobile-first approach with Tailwind breakpoints
  6. Security: CORS configuration, JWT validation, ownership verification

Database Schema

The app uses 6 tables in Neon PostgreSQL β€” 1 application table and 5 managed by Better Auth.

tasks (Application Table)

Column Type Constraints
id UUID Primary key, auto-generated
user_id VARCHAR(255) Not null, indexed β€” links to user.id
title VARCHAR(200) Not null
description TEXT Optional
completed BOOLEAN Not null, default: false
created_at TIMESTAMPTZ Auto-set on insert
updated_at TIMESTAMPTZ Auto-updated via trigger

Indexes: idx_tasks_user_id, idx_tasks_user_created (user_id, created_at DESC), idx_tasks_user_completed (user_id, completed)

user (Better Auth)

Column Type Constraints
id TEXT Primary key
name TEXT Not null
email TEXT Not null, unique
emailVerified BOOLEAN Default: false
image TEXT Optional
createdAt / updatedAt TIMESTAMP Auto-managed

session (Better Auth)

Column Type Constraints
id TEXT Primary key
token TEXT Not null, unique
expiresAt TIMESTAMP Not null (7 days TTL)
userId TEXT FK β†’ user.id CASCADE DELETE
ipAddress / userAgent TEXT Optional
createdAt / updatedAt TIMESTAMP Auto-managed

account (Better Auth)

Stores hashed passwords (email/password auth) or OAuth tokens per user.

Column Type Notes
id TEXT Primary key
providerId TEXT e.g. credentials, google
accountId TEXT Provider-side user ID
password TEXT Hashed password (null for OAuth)
userId TEXT FK β†’ user.id CASCADE DELETE
accessToken / refreshToken / idToken TEXT OAuth tokens (null for email auth)

verification (Better Auth)

Temporary tokens for email verification and password reset flows.

Column Type Notes
id TEXT Primary key
identifier TEXT Email being verified
value TEXT The verification token
expiresAt TIMESTAMP Short-lived (typically 1 hour)

jwks (Better Auth JWT Plugin)

Stores the EdDSA key pair used to sign and verify JWT tokens.

Column Type Notes
id TEXT Primary key
publicKey TEXT Exposed at /api/auth/jwks β€” used by backend to verify tokens
privateKey TEXT Encrypted with BETTER_AUTH_SECRET β€” used to sign JWTs
createdAt TIMESTAMP Key generation time

Note: If you change BETTER_AUTH_SECRET, delete all rows in jwks so Better Auth regenerates the key pair with the new secret. Otherwise login will fail with a decryption error.

πŸ“ License

This project is part of Phase 2 of the Hackathon Todo project.

🀝 Contributing

This is a learning project for implementing spec-driven development with full-stack technologies.

πŸ“ž Support

For issues or questions:

  1. Check the documentation in /specs
  2. Review the implementation plan in /specs/001-phase2-implementation/plan.md
  3. See testing procedures in backend/TESTING.md

Built with: Next.js β€’ FastAPI β€’ PostgreSQL β€’ TailwindCSS β€’ Better Auth β€’ TypeScript β€’ Python

Phase 2 Full-Stack Implementation - December 2025

About

A ToDo App

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages