What We're Building
A task management app called Taskflow. Not a toy — a real, deployable application with authentication, a database, a REST API, and a polished frontend. The kind of project that typically takes a week or two of focused work.
We're building it in a weekend using AI-first methodology. Every decision, every component, every test — AI participates. You drive, AI accelerates.
Feature Set
- Projects — Create, rename, archive projects to group related tasks
- Tasks — Full CRUD with title, description, status, priority, due date, assignment
- Kanban board — Drag-and-drop columns: To Do, In Progress, Review, Done
- Filtering & search — By status, priority, assignee, and text search
- Authentication — JWT-based login/register with secure password hashing
- Responsive — Works on desktop and mobile
Tech Stack
We're choosing this stack deliberately: React and TypeScript because they're the dominant frontend combination, Tailwind because it eliminates CSS bikeshedding, Express because it's minimal and fast to set up, and SQLite because it requires zero configuration — no Docker, no database server, just a file. Everything optimized for weekend speed.
Pro Tip: Why This Stack
In a weekend build, every minute of configuration is a minute not spent building features. SQLite eliminates database setup entirely. Tailwind eliminates CSS design decisions. TypeScript catches errors before runtime so you debug less. Every choice in this stack reduces friction.
The Weekend Schedule
Here's the realistic timeline. Five parts, roughly mapping to five focused sessions. You don't need to follow this exactly — adjust to your pace. The key is the sequence: planning before code, review before moving on.
Step 1: Design the Architecture
We're starting exactly how the AI Programming Manual teaches: design before code. Here's the actual conversation with AI that produces our architecture.
I'm building a task management app called Taskflow this weekend. React 18 + TypeScript frontend, Express + SQLite backend, Tailwind for styling.
Features: projects, tasks with full CRUD, kanban board with drag-and-drop, filtering, JWT authentication.
Design the architecture. Show me: data model, API endpoints, component tree, and state management approach.
Constraint: must be buildable by one developer in a weekend. Optimize for speed, not scale.
Data Model
Three tables: users (id, email, password_hash, name, created_at), projects (id, name, owner_id, archived, created_at), tasks (id, project_id, title, description, status, priority, assignee, due_date, position, created_at, updated_at).
Status enum: todo | in_progress | review | done
Priority enum: low | medium | high | urgent
API Endpoints
Auth: POST /auth/register, POST /auth/login
Projects: GET /projects, POST /projects, PATCH /projects/:id, DELETE /projects/:id
Tasks: GET /projects/:id/tasks, POST /projects/:id/tasks, PATCH /tasks/:id, DELETE /tasks/:id, PATCH /tasks/:id/move (for kanban reorder)
Component Tree
App → AuthProvider → Router → { LoginPage, RegisterPage, DashboardLayout → { Sidebar (project list), ProjectView → { FilterBar, KanbanBoard → { Column → TaskCard* } }, TaskModal } }
State Management
For weekend speed, I recommend Zustand over Redux. Two stores: useAuthStore (user, token, login/logout) and useProjectStore (projects, tasks, CRUD actions). API calls inside Zustand actions, no separate service layer — minimize indirection for speed.
One prompt, and we have a complete architecture. But we're not done — next comes the critique step.
Step 2: Critique the Design
Now critique this design. Be ruthless. What will break? What's over-engineered for a weekend build? What's missing?
Issues found:
1. Assignee field is a string — This works for solo use but breaks if you want multi-user assignment later. For weekend scope this is fine, but note the limitation.
2. Position field for kanban ordering — Reordering with integer positions leads to frequent renumbering. Use float positions instead (e.g., insert between 1.0 and 2.0 → 1.5). Cheaper operations.
3. Missing: task moved_at timestamp — If you track when a task was moved to "done," you get basic velocity metrics for free. Add completed_at.
4. DELETE /projects/:id is dangerous — Should this cascade-delete all tasks? Add a soft-delete (archive) instead. You already have an archived field — use it.
5. No error handling strategy defined — Define upfront: API returns { error: string, code: string } on failure. Frontend shows toast notifications.
6. CORS not mentioned — Will bite you immediately. Add to the architecture: cors({ origin: 'http://localhost:5173' }).
Six issues found in under a minute. Issues 2, 4, 5, and 6 would have become debugging sessions later. By finding them now, we've saved at least an hour of weekend time.
Design → Critique → Improve. Every time. The critique step is where the real quality comes from. If you skip it, you're just generating code with extra steps. If you do it, you're building on a solid foundation.
Step 3: The Improved Architecture
Incorporating the critique, here's our validated architecture:
Step 4: Define Milestones
Breaking the build into small, testable milestones. Each milestone produces something you can verify before moving on. This prevents the "everything is half-done" problem.
Project scaffolding
Monorepo with /client and /server. Both run with hot reload. CORS configured.
Database & models
SQLite setup, schema migration, TypeScript types for all entities.
Authentication
Register, login, JWT middleware, protected routes. Test with curl.
Project CRUD API
All project endpoints working. Archive instead of delete. Test with curl.
Task CRUD API
All task endpoints including kanban move with float positioning. Full test suite.
Frontend auth flow
Login/register pages, Zustand auth store, protected routes, token persistence.
Dashboard & project list
Sidebar with projects, create/archive, DashboardLayout with routing.
Kanban board
Columns render tasks by status. TaskCards display key info. Create task modal.
Drag-and-drop & filtering
Move tasks between columns. FilterBar with status, priority, search.
Polish, test & deploy
Responsive design, security review, test suite, error handling, deployment.
Total estimated time: ~8 hours of focused work. That's a weekend with breaks. Each milestone is independently verifiable — you know it works before moving on.
Step 5: Define the Types
Before writing any implementation code, we define the TypeScript types. These types become the contract that both frontend and backend must respect — and they're the single most important context to share with AI throughout the build.
// === Entities ===
export interface User {
id: string;
email: string;
name: string;
created_at: string;
}
export interface Project {
id: string;
name: string;
owner_id: string;
archived: boolean;
created_at: string;
}
export type TaskStatus = 'todo' | 'in_progress' | 'review' | 'done';
export type TaskPriority = 'low' | 'medium' | 'high' | 'urgent';
export interface Task {
id: string;
project_id: string;
title: string;
description: string;
status: TaskStatus;
priority: TaskPriority;
assignee: string | null;
due_date: string | null;
position: number;
completed_at: string | null;
created_at: string;
updated_at: string;
}
// === API Request/Response ===
export interface CreateTaskInput {
title: string;
description?: string;
status?: TaskStatus;
priority?: TaskPriority;
assignee?: string;
due_date?: string;
}
export interface UpdateTaskInput {
title?: string;
description?: string;
status?: TaskStatus;
priority?: TaskPriority;
assignee?: string | null;
due_date?: string | null;
}
export interface MoveTaskInput {
status: TaskStatus;
position: number;
}
export interface ApiError {
error: string;
code: string;
}
Pro Tip: Types Are Your Best Context
Throughout this build, every time you ask AI to generate code, paste these types first. They're compact (40 lines), they define the entire data contract, and they prevent AI from inventing its own field names or types. This single file will save you more debugging time than anything else in the project.
Resist the urge to start implementing. You now have: a validated architecture, a critique-tested design, 10 defined milestones, and shared types. This planning session took about 30 minutes. It will save you 3+ hours of rework during the build.
If you skipped straight to code, you'd be refactoring your database schema by milestone 5 and rewriting your API by milestone 8. We've already prevented that.
Part 1 Complete — What We Have
- Validated architecture: three-layer system (React → Express → SQLite) with all components defined
- Critique-tested design: six potential issues found and resolved before writing any code
- Data model: three tables with all fields, enums, and relationships defined
- API design: 11 endpoints with methods, paths, and behaviors specified
- Component tree: 13 components with clear hierarchy and responsibilities
- 10 milestones: each independently testable, with time estimates totaling ~8 hours
- Shared TypeScript types: the contract both frontend and backend will respect