Skip to content

rawadhossain/TaskFlow

Repository files navigation

Task-Flow

Task-Flow

Production-minded personal task management — persisted, validated, and ready to run end-to-end
Full-stack TypeScript, PostgreSQL, Google sign-in, smart views, tags, subtasks, trash & restore, stats.

TanStack Start   TypeScript   React   Tailwind CSS   Prisma   PostgreSQL

Overview  ·  Screenshots  ·  Features  ·  Stack  ·  Getting started  ·  API & server  ·  Data model  ·  Rubric  ·  Deploy


Overview

Task-Flow is a browser-based task manager with a real database, shared client/server validation, and HTTP-backed server execution. It was built to satisfy the Acme / intern take-home brief (see Acme.md in this repo): view, create, edit, toggle status, and remove tasks, with filters and clear error handling.

The reference brief assumed a single anonymous user and a small REST surface. This submission extends that baseline with Google OAuth (Better Auth), per-user data isolation, soft delete + trash, and a richer domain (tags, subtasks, priorities, due dates, drag reorder, keyboard shortcuts). Where behavior differs from the literal brief, it is called out under Deviations & design choices.

Table of contents

Screenshots

Task-Flow dashboard: task list, filters, productivity sparkline, today progress, and keyboard shortcuts sidebar
Dashboard (/tasks) — filters, productivity trends, insights, quick add, and side panels.

Features

Brief expectation Implementation
List tasks (title, description, status, created date) Task list & smart views (/tasks, Today, Upcoming, Completed); cards show metadata, tags, subtask progress
Add task (title required, optional description) Quick-add bar + full modal; persisted via server
Toggle complete / incomplete Checkbox / status control with optimistic updates
Delete task Soft delete by default (recoverable); permanent delete from Trash uses a confirmation dialog
Edit task Edit modal + inline flows where supported
Filter All / Pending / Completed Filters + search + sort; state can sync to URL
Validation: reject empty title, show errors Zod on server functions; React Hook Form + Zod in UI
Persist in a real DB PostgreSQL via Prisma; no localStorage as primary store

Additional (beyond minimum): tags, subtasks, priorities, due dates (with overdue emphasis), stats, drag-to-reorder, trash restore, bulk actions, dark/light theming.

Tech stack

Layer Choice
Application TanStack Start — React 19, Vite 7, SSR-ready
Routing TanStack Router (file-based routes under src/routes/)
Server I/O TanStack createServerFn (type-safe RPC over HTTP), Zod input validation
ORM & migrations Prisma 7 → PostgreSQL
Auth Better Auth + Google OAuth
Client data TanStack Query
Forms React Hook Form + Zod resolver
Styling Tailwind CSS 4 + app-specific tokens / components
Tests Vitest (unit), Playwright (E2E)

Architecture

Browser (React)
    │  TanStack Query
    ▼
Server functions (src/lib/*.functions.ts)
    │  session (Better Auth), Zod parse
    ▼
Repositories (src/lib/*.repo.ts)
    │  Prisma, scoped by userId
    ▼
PostgreSQL
  • Single deployable app: “frontend” and “backend” share one process in development and one build for production; the client does not talk to the database directly.
  • Auth boundary: Better Auth serves /api/auth/*. Task server functions call auth.api.getSession and refuse work without a user.
  • Conventions: Domain validation lives in src/lib/validations/. Deeper product rules are documented in FEATURES.md and AGENTS.md.

API & server contract

The Acme brief lists REST endpoints (GET/POST /api/tasks, PUT/PATCH/DELETE /api/tasks/:id, etc.). This project implements the same operations as authenticated server functions (POST-shaped RPC handlers generated by TanStack Start) rather than hand-written Express-style routers.

Why this still satisfies “HTTP API” expectations: each call is an HTTP request from the browser to the app server, returns JSON-shaped data, and uses validation + error semantics appropriate for production (invalid input rejected on the server; unauthenticated calls blocked).

Conceptual mapping:

Brief endpoint This codebase
GET /api/tasks listTasksFn — list/filter/paginate tasks for the signed-in user
POST /api/tasks createTaskFn
PUT /api/tasks/:id updateTaskFn
PATCH /api/tasks/:id/toggle toggleTaskFn
DELETE /api/tasks/:id deleteTaskFnsoft delete (see Deviations); trash purge uses permanentDeleteTaskFn

Auth routes remain standard HTTP: Better Auth under /api/auth/*.

Data model

The brief’s minimal tasks table maps to the Prisma Task model (extended for production):

Brief field Prisma / notes
id String / cuid
title VarChar(255), required
description Text, optional
status TaskStatus enum (PENDING, IN_PROGRESS, COMPLETED)
created_at / updated_at createdAt, updatedAt
priority, dueDate, position, isDeleted, deletedAt, userId, relations to Subtask, Tag

See prisma/schema.prisma and migrations under prisma/migrations/.

UI, responsiveness & accessibility

  • Mobile-first layout: dashboard shell, sidebar, bottom navigation, and task lists adapt down to phone widths (~375px).
  • Brief UI checklist: list + create + toggle + delete/edit flows + empty-title errors + pending vs completed visuals (styling, icons, motion where appropriate).
  • Components: Radix-based primitives (dialogs, alerts) for confirmations and focus management.

Prerequisites

  • Node.js 22.x (LTS) or newer — nodejs.org
  • PostgreSQL — local or hosted (e.g. Neon)
  • Google OAuth app — client ID & secret; authorized redirect: {BETTER_AUTH_URL}/api/auth/callback/google
  • Bun (optional) — some scripts invoke bunx; see Local setup for a pure npx fallback

Local setup

Target: clone → install → env → migrate → run in under 10 minutes on a machine that already has Node and a blank PostgreSQL database.

  1. Clone

    git clone <YOUR_REPO_URL> task-flow
    cd task-flow
  2. Install

    npm install
  3. Environment

    cp .env.example .env

    Fill in DATABASE_URL, BETTER_AUTH_URL (dev: http://localhost:5173), BETTER_AUTH_SECRET (≥ 32 random chars), GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET.

  4. Schema

    npm run db:migrate
  5. Seed (optional)

    npm run db:seed

    If bunx is missing:

    npx tsx --tsconfig tsconfig.json prisma/seed.ts

    Seeding creates dev@taskflow.local plus sample rows for Prisma Studio; your Google account is a separate user unless you align emails deliberately.

  6. Develop

    npm run dev

    Default dev URL: http://localhost:5173 (see playwright.config.ts). Sign in with Google → land on /tasks.

Environment variables

Variable Required Purpose
DATABASE_URL Yes PostgreSQL URL (sslmode=require for Neon)
BETTER_AUTH_URL Yes Public app origin (https://… in production)
BETTER_AUTH_SECRET Yes Session signing secret (≥ 32 chars)
GOOGLE_CLIENT_ID Yes* OAuth client ID
GOOGLE_CLIENT_SECRET Yes* OAuth client secret
VITE_BETTER_AUTH_URL Optional When the SPA is served from a different origin than the server
SKIP_ENV_VALIDATION Optional e.g. 1 in CI helpers

*Required for Google sign-in. Never commit .env — only .env.example.

Scripts

Command Description
npm run dev Dev server (Vite + TanStack Start)
npm run build Production build (Nitro preset for Vercel-style output when VERCEL=1)
npm run preview Preview production build locally
npm run lint ESLint
npm run format Prettier
npm run db:generate prisma generate
npm run db:migrate prisma migrate dev
npm run db:migrate:deploy prisma migrate deploy (CI / production)
npm run db:seed Seed script
npm run db:studio Prisma Studio
npm test Vitest
npm run test:e2e Playwright

Testing & quality

  • Unit / integration-style tests under tests/unit/ (e.g. validation, repository behavior).
  • E2E under tests/e2e/ via Playwright (PLAYWRIGHT_BASE_URL overrides default host).
  • Linting: npm run lint before merge; TypeScript strictness as configured in tsconfig.json.

Project structure

├── docs/
│   └── taskflow-mark.svg
├── public/
│   └── dashboard.jpeg      # Screenshots (README)
├── prisma/
│   ├── schema.prisma
│   ├── migrations/
│   └── seed.ts
├── src/
│   ├── routes/              # File routes + layouts
│   ├── components/          # Dashboard UI, primitives
│   ├── hooks/
│   ├── lib/
│   │   ├── auth.ts
│   │   ├── *.functions.ts   # Server functions
│   │   ├── *.repo.ts        # Prisma access
│   │   └── validations/     # Zod schemas
│   └── generated/prisma/
├── tests/
│   ├── unit/
│   └── e2e/
├── Acme.md                  # Assignment brief & rubric (evaluation source)
├── .env.example
├── AGENTS.md
├── FEATURES.md
└── README.md

Security & authentication

  • Secrets only via environment variables (src/env.ts / T3-style validation).
  • Sessions via Better Auth; task queries always scoped by userId.
  • No raw Prisma errors leaked to clients on failure paths — errors logged server-side, safe messages to the UI.
  • Google OAuth: configure production callback URLs to match BETTER_AUTH_URL.

Deployment

  1. Set production environment variables (same keys as .env.example; BETTER_AUTH_URL must equal the public site origin).
  2. Run npm run db:migrate:deploy against the production database.
  3. Register {BETTER_AUTH_URL}/api/auth/callback/google in Google Cloud Console.

Vercel (recommended path for this repo)

The Vite config disables the default Cloudflare build for production when using Nitro and sets cloudflare: false so npm run build can emit output Vercel expects when VERCEL=1. Do not point Vercel at a Cloudflare-only output directory unless you intentionally target Workers.

Cloudflare Workers (optional)

wrangler.jsonc points at src/server.ts for an alternative hosting model.

Live demo (optional): add your public URL here after deploy:

https://YOUR_PRODUCTION_DOMAIN

About

A focused, personal task manager with smart views, color tags, and a real-time momentum ring - built for people who actually want to finish things.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors