Taskmaster is an AI-assisted task management app that helps users decide what to work on next, break down overwhelming tasks, and stay motivated with personalized feedback.
The goal of this project is not only to build a useful productivity app, but also to learn the technologies behind a modern full-stack TypeScript application step by step.
Most task apps help users store tasks. Taskmaster should help users make better decisions about those tasks.
The app will eventually support:
- Creating and managing personal tasks
- AI-suggested priority levels
- AI explanations for why a task is important
- AI-generated steps for completing tasks
- Notes and resources attached to each task
- A suggested daily task order
- Completion encouragement messages
- A dashboard for progress, overdue tasks, and completed work
| Area | Technology | Purpose |
|---|---|---|
| Framework | Next.js | Full-stack React app structure |
| Language | TypeScript | Type safety and better developer tooling |
| UI | React | Component-based interface |
| Styling | Tailwind CSS | Utility-first styling system |
| Components | shadcn/ui and Base UI | Accessible, reusable UI building blocks |
| Icons | Lucide React | Consistent icon system |
| Formatting | Prettier | Consistent code formatting |
| Linting | ESLint | Code quality checks |
| Database | PostgreSQL | Persistent relational data storage |
| ORM | Prisma | Type-safe database queries and migrations |
| Auth | Clerk | User accounts and protected routes |
| AI | Vercel AI SDK, Google Gemini, and Zod | Structured, validated task recommendations |
| Deployment | Vercel | Hosting for the Next.js app |
| Database Hosting | Neon or Supabase | Hosted PostgreSQL database |
The first useful version of Taskmaster should include:
- User authentication
- Create, edit, delete, and complete tasks
- Store tasks in a database
- Suggest a priority level for each task using AI
- Generate task completion suggestions using AI
- Show a suggested daily order
- Display a simple progress dashboard
This project is being built in modules so each step has a clear learning goal.
- Project identity and README
- Landing page
- Task UI with temporary data
- Task create/edit/delete/complete interactions
- Prisma and PostgreSQL setup
- Persist tasks in the database
- Authentication with Clerk
- User-owned private tasks
- AI priority suggestions
- AI task completion suggestions
- Daily planning flow
- 11.1 Collapsible daily-plan sidebar
- Completion encouragement messages
- Dashboard and progress stats
- 14.1 Simplified command-center header and responsive metric ribbon
- Testing, accessibility, and security hardening
- Deployment and portfolio readiness
Install dependencies:
pnpm installRun the development server:
pnpm devRun code quality checks:
pnpm lint
pnpm typecheck
pnpm test
pnpm test:integration:docker
pnpm test:e2eRun only automated browser accessibility checks with pnpm test:a11y, or run the complete local Module 15 workflow with pnpm test:all.
Generate the Prisma client after changing the database schema:
pnpm db:generateApply Prisma schema changes to your PostgreSQL database:
pnpm db:migrateOpen Prisma Studio to inspect database rows visually:
pnpm db:studioOpen the app locally:
http://localhost:3000Taskmaster uses Neon-hosted PostgreSQL with Prisma as the TypeScript database layer.
- Create a Neon PostgreSQL database.
- Copy
.env.exampleto.env. - Paste your Neon connection string into
DATABASE_URL. - Run
pnpm db:generateto generate Prisma Client. - Run
pnpm db:migratewhen you are ready to create the database tables.
The Prisma Task model stores Clerk's userId as the ownership key. PostgreSQL indexes that field so user-scoped queries remain efficient as the table grows. The field remains nullable only for pre-auth development rows; new application writes always include an owner.
Task completion stores a dedicated nullable completedAt timestamp in the same trusted status update. Reopening clears it, and older completed rows remain historically unknown instead of being assigned an invented completion date.
Taskmaster uses risk-based test layers instead of one broad runner:
pnpm testruns fast Vitest unit and React Testing Library component tests without PostgreSQL, Clerk credentials, or Gemini.pnpm test:integration:dockerstarts a disposable local PostgreSQL container, applies all migrations, runs serial ownership/constraint/quota/transaction tests, and removes its data afterward.pnpm test:e2ebuilds and starts the production-like Next.js app for credential-free Playwright route, keyboard, responsive, reduced-motion, and axe checks.pnpm test:a11yruns the tagged automated axe browser checks.pnpm test:allruns the fast, disposable-database, and browser layers in sequence.
Integration helpers require the dedicated local TEST_DATABASE_URL and reject missing configuration, DATABASE_URL reuse, remote hosts, other ports, and non-test database names. Automated provider tests use controlled doubles and never read a live Gemini key or spend quota. Browser tests intentionally omit authenticated CRUD until dedicated Clerk test-instance credentials and isolated test users exist; Server Action and PostgreSQL tests cover authentication ordering and cross-user isolation meanwhile.
Before completing a module, manually check keyboard order and visible focus, 200% and 400% zoom/reflow, narrow-screen overflow, contrast, reduced motion, and status/error announcement quality. See tests/README.md for test boundaries and Docker debugging commands.
Taskmaster uses Clerk for sign-in, sign-up, session handling, and protected server resources.
- Create a Clerk application.
- Copy the publishable and secret keys from the Clerk Dashboard API Keys page.
- Add both values to your local
.envusing the names shown in.env.example. - Run
pnpm devand create the first test account from the landing page.
The /tasks page and every task Server Action require a signed-in user.
Taskmaster uses the Vercel AI SDK with Google's Gemini provider. AI calls run only on the server, and Zod validates each structured model response before the browser receives it.
- Create a Google AI Studio API key at
https://aistudio.google.com/app/apikey. - Add it to your local
.envasGOOGLE_GENERATIVE_AI_API_KEY. - Restart
pnpm devafter changing environment variables. - Open an add or edit form, enter a title and description, and select Suggest priority.
- Save a task and select Generate action plan on its card for completion guidance.
- Select Plan my day to compare all active tasks in one Gemini request.
The key is intentionally not prefixed with NEXT_PUBLIC_, so Next.js does not include it in browser JavaScript. Gemini classifies one task at a time; ordinary TypeScript then sorts active tasks High, Medium, and Low without spending more AI quota. Generating or regenerating a completion plan makes one additional Gemini request.
Completion-plan buttons send only a task id. The Server Action authenticates the Clerk session, loads the owned task from PostgreSQL, and gives Gemini that trusted task data. Zod requires one summary and two to five ordered steps before Prisma stores the summary as text and the steps as a PostgreSQL text array. Editing a task clears its previous plan because guidance generated from old details may no longer be accurate.
Daily planning is limited to two successful generations per user per UTC calendar day: the initial plan and one regeneration. PostgreSQL creates a unique short-lived reservation before the provider call and removes it when generation or persistence fails; abandoned reservations expire after five minutes. The usage row is separate from the current plan, so replacing, deleting, refreshing, or manually reordering a plan cannot reset the allowance.
Gemini must return every active task id exactly once. Application validation rejects missing, duplicate, or invented ids before Prisma transactionally replaces the current plan. Move Up and Move Down controls persist a human-selected order without calling Gemini. A plan remains a snapshot when tasks later change; newly created tasks use normal priority sorting until the next allowed regeneration.
The generated plan appears in a left-side sidebar on wide screens and stacks before task cards on smaller screens. It starts expanded, can collapse into a narrow rail, keeps the main Gemini summary, and uses compact reorderable task rows without repeating each stored item rationale.
Clerk handles identity and supplies the authenticated userId. Server Actions use that trusted id in every Prisma where clause, while PostgreSQL returns only matching rows. The browser never chooses or submits task ownership.
This separates the security responsibilities:
- Clerk authentication establishes who made the request.
- Next.js Server Actions enforce authorization near database access.
- Prisma expresses ownership filters in type-safe queries.
- PostgreSQL stores and indexes the ownership key.
By building this app, the goal is to understand and be able to discuss:
- How Next.js structures pages, layouts, and server-side logic
- How React components manage UI and user interactions
- How TypeScript makes application code safer
- How Tailwind CSS helps build responsive layouts quickly
- How reusable UI components are organized
- How Prisma models database tables and relationships
- How authentication connects users to private data
- How AI features are called from server-side code
- How to validate and protect user input
- How to deploy a full-stack app with environment variables
Initialized with Next.js, TypeScript, Tailwind CSS, shadcn/ui, Base UI, ESLint, Prettier, and Lucide icons.
The public landing page now introduces the product with a branded hero, temporary logo mark, tagline, login call-to-action, and task preview card.
The temporary task workspace at /tasks now uses mock task data to render task cards, priority labels, statuses, AI suggestion copy, and dashboard counters.
The /tasks workspace now supports temporary browser-only task interactions: create, edit, complete, reopen, and delete.
Prisma and PostgreSQL setup has been added with a first Task schema, a Prisma config file, database scripts, and a reusable Prisma Client helper.
The /tasks workspace now reads from PostgreSQL and uses server actions to create, edit, delete, complete, and reopen persisted tasks.
Clerk authentication now provides sign-in/sign-up controls, session-aware landing content, a user menu, and authentication checks around the task page and task Server Actions.
All task reads and mutations are now scoped to the authenticated Clerk user, creating private per-user task lists in a shared PostgreSQL database.
Gemini now recommends a priority for one task at a time through an authenticated Server Action. The AI SDK requests structured output, Zod validates its priority and rationale, and accepted results persist in PostgreSQL while remaining manually overridable.
Saved task cards can now generate or regenerate a Gemini completion plan. Each validated plan contains a summary and two to five ordered steps, persists in PostgreSQL, and remains available after a refresh.
The dashboard can now compare up to 25 active tasks in one AI-assisted daily planning request, persist one current focus sheet, sort task cards by focus position, and save manual up/down changes without spending AI quota. Server-side UTC usage tracking permits only an initial plan and one regeneration each day.
The daily focus sheet now uses an expanded-by-default responsive sidebar. Users can collapse it without changing saved plan data, while focus badges, card ordering, completion state, and manual movement continue to use the existing persisted plan.
Completing a task now triggers a brief, non-modal amber celebration with a Task Complete! status message. The deterministic effect starts only after the owned database mutation succeeds, respects reduced-motion preferences, fades automatically, and uses no Gemini request or persisted presentation state.
Module 13 task notes/resources was intentionally removed because it does not serve the intended workflow. The remaining roadmap keeps its established numbering.
The workspace now pairs a simplified Command Center header with the shared Taskmaster mark and a compact responsive metric ribbon. The ribbon derives active and overdue work, completions in the Monday-start UTC week, and current UTC daily-focus progress from the user's loaded owned tasks and plan without calling Gemini. Historical Done tasks without a trusted completion timestamp remain excluded from weekly totals.
Module 15 adds layered Vitest, Testing Library, disposable PostgreSQL, Playwright, and axe coverage around deterministic metrics, runtime validation, authentication and ownership, structured AI output, quota concurrency, rollback, responsive behavior, and accessible interaction. Expected task and planning failures now preserve committed state and expose retryable feedback, while unexpected workspace-load failures use a safe route recovery screen.
Next step: deployment, environment configuration, CI checks, observability, final documentation, and portfolio readiness in Module 16.