I use TaskFlow AI’s versioned REST API for profile, workspace, project, task, and comment operations. Routes use the /api/v1 prefix; protected requests rely on a session cookie, and browser writes must satisfy the API’s origin and JSON requirements.
I authenticate protected API requests with the taskflow_session HttpOnly cookie.
For browser writes, I include the configured Origin and send JSON with Content-Type: application/json.
My list pagination defaults are page 1, pageSize 20, maximum 100.
For workspace member role changes, only owner can grant/change admin; owner removal requires ownership transfer first.
I make new workspace membership invitation-based; direct member creation is intentionally not exposed.
In my project API, workspace members can read projects and non-guests can create them.
In my project API, a project admin or workspace admin can update, delete, or archive a project; member changes also require project or workspace admin access.
In my task API, project reads follow project access, while task writes require project ADMIN or MEMBER access or workspace admin access.
For task endpoints, reading and editing follow project role, but deleting requires project or workspace admin access.
A task writer can change task status and assign or unassign a task; an assignee must be a workspace member, and null unassigns.
A project reader can list task comments, while a task writer can add comments.
My dashboard reads the workspace overview for project progress, task status totals, upcoming deadlines, member count, and recent activity.
My project lists and statistics are workspace-scoped and limited to projects visible to the current user.
When I create a project, the creator is automatically added as project administrator.
To add a project member, the user must already belong to the same workspace.
My task list filters are page, pageSize, status, priority, assigneeId, search, dueBefore, dueAfter; unassigned means no assignee.
My task creation example uses priority HIGH, dueAt 2026-10-20T17:00:00Z, status TODO.
Workspace OWNER/ADMIN can read and manage every project.
Other members and guests see only projects where they have project membership.
Project VIEWER is read-only; MEMBER can create and update tasks/comments, and project ADMIN can also manage project settings and members.
For resource access outside the caller’s workspace, my API returns 404 to avoid disclosing existence.
My mutations record actor, action, and relevant resource in ActivityLog within the same database transaction where applicable.
I’m building TaskFlow AI, an AI-powered project management SaaS. Its current repository is a TypeScript monorepo development foundation with a Next.js frontend, an Express API, shared Zod contracts, and a Prisma/PostgreSQL package. The frontend and API are independently runnable workspace applications.
I started the taskflow-ai repository in 2026-10, and it was last updated in 2026-10.
- I need Node.js 22.9 or newer (Node.js 22 LTS recommended), pnpm 11.19.0, and PostgreSQL 14 or newer for this repository.
The workspace is divided between apps/api for the Express REST API, authentication, authorization, and tests; apps/web for the Next.js App Router frontend; packages/contracts for shared Zod schemas and TypeScript types; and packages/database for the Prisma schema, migrations, and shared database client.
- I install dependencies with
pnpm installand approve only named lifecycle scripts required by the workspace, including Prisma engines and esbuild.
Copy-Item .env.example .env
pnpm db:generate
pnpm db:migrate
I set DATABASE_URL to an accessible PostgreSQL database; the example URL is a local development placeholder, not a production credential. I create the database itself first if it does not exist.
For an existing shared, staging, or production database, I use reviewed checked-in migrations with pnpm db:migrate:deploy; pnpm db:push is prototype-only schema sync and does not create migrations.
I provide production DATABASE_URL through the deployment environment rather than a checked-in file, and I do not commit .env or put secrets in NEXT_PUBLIC_* variables because Next.js exposes those values to the browser.
pnpm dev:web
pnpm dev:api
I access the local frontend at http://localhost:3000 and the API health endpoint at http://localhost:4000/api/v1/health.
| Command | Purpose |
|---|---|
pnpm dev:web | Start Next.js in development mode |
pnpm dev:api | Start Express with automatic TypeScript reload |
pnpm build:api | Build the database client package and Express API |
pnpm test:api | Run API unit, route, validation, and optional PostgreSQL workflow tests |
pnpm build:web | Build the frontend for production |
pnpm typecheck | Type-check all workspace packages |
pnpm lint | Lint all workspace packages |
pnpm format | Format tracked and unignored files with Prettier |
pnpm format:check | Check formatting without modifying files |
pnpm db:generate | Generate the Prisma client |
pnpm db:migrate | Create/apply local development migrations |
pnpm db:migrate:deploy | Apply checked-in migrations in shared environments |
pnpm db:migrate:status | Show whether migrations have been applied |
pnpm db:push | Prototype-only schema sync; does not create migrations |
pnpm db:studio | Open Prisma Studio |
I add a frontend component from the repository root with the local shadcn/ui CLI, for example pnpm --filter @taskflow/web run ui add button; the frontend uses Tailwind CSS and is configured for shadcn/ui.
My API CORS allows the configured WEB_ORIGIN, which defaults to the local frontend origin. The health endpoint is a process liveness check and does not verify database readiness.
Authentication and core project, task, and team screens use the PostgreSQL-backed API; notifications and the AI assistant remain demo-only until their backend modules are available.
My browser API client uses NEXT_PUBLIC_API_BASE_URL and sends the HttpOnly session cookie with requests. Next.js server-rendered workspace pages use API_INTERNAL_BASE_URL and forward only the session cookie to Express; the session token is never stored in browser JavaScript storage.
My project and task forms use native browser input validation and send JSON through the shared API client. Express validates each request with Zod and authorizes against the authenticated database session.
My Prisma schema defines users and provider accounts and sessions; workspace and project membership join tables; projects and hierarchical tasks; comments, file metadata attachments, task dependencies, notifications, activity history, invitations, and a transactional outbox for real-time delivery.
My membership tables keep roles and membership timestamps on the relationship, and compound unique constraints prevent duplicate memberships. Indexes cover workspace and project lists, board columns and ordering, assignee queues, deadlines, unread notifications, activity timelines, and unpublished outbox events.
Deleting a workspace cascades through its projects and collaboration records, and deleting a project cascades through its tasks and task content. Deleting a user removes login and membership records while preserving authored content and history with nullable author references where appropriate.
My session, password-reset, and invitation tokens are stored as hashes; the application must encrypt OAuth credentials before persistence. Email addresses are stored lowercase, and task and invitation invariants are enforced by checks in the initial SQL migration.
My Prisma transactions cover project creation with its first administrator membership and activity record, and task changes with activity records. Parent tasks and assignees are checked against the current project or workspace before writes.
Invitation acceptance and outbox delivery remain future work. A worker can publish outbox rows to Socket.IO and retry failed delivery.
My authentication architecture follows this rule: The Express API owns credential verification and opaque database sessions.
My registration flow is transactional: Registration validates and normalizes input, hashes passwords with Node.js scrypt, then creates the user, owner membership, initial workspace, and session in one transaction.
My browser-session design is: The browser receives only a random session token in an HttpOnly, SameSite=Lax cookie; PostgreSQL stores its SHA-256 hash and expiration.
My Next.js workspace layout checks authentication before rendering: The Next.js workspace layout calls the protected /auth/me endpoint before rendering.
I require independent authentication checks for API routes: every API route verifies the session independently.
My session-management endpoints include POST /api/v1/auth/login, /register, and /logout manage sessions.
My profile endpoint behavior is: /auth/me reads and updates the current profile.
My session-management endpoint behavior is: /auth/sessions lists the current user’s active sessions and allows revocation.
I require workspace membership for reads: Workspace reads require membership.
My workspace-rename authorization rule is that workspace renames require an OWNER or ADMIN role fetched from PostgreSQL.
I do not accept role claims from request bodies: Request bodies cannot supply effective roles.
My password-reset flow uses Password reset uses short-lived, one-use hashed tokens.
My password-reset responses use generic responses to prevent account discovery.
After a successful password reset, my system revokes all sessions after a successful reset.
For local development, I follow this cookie-domain policy: Keep SESSION_COOKIE_DOMAIN empty for local development.
I set the cookie domain in production only under this condition: set it only when the frontend and API use related production hosts.
My proxy policy is: Set TRUST_PROXY=true only behind a trusted reverse proxy.
My current rate limiter is process-local: The current rate limiter is process-local.
Before running multiple API instances, I need to use a shared store before running multiple API instances.
I enable password-reset email delivery with this configuration: Configure EMAIL_DELIVERY_URL, EMAIL_DELIVERY_TOKEN, and EMAIL_FROM to enable password-reset email delivery.
My email-delivery request format is: The delivery service accepts a JSON POST with from, to, subject, and text fields.
My email-delivery settings are server-only: These settings are server-only.
I run pnpm test:api to build the database package and API: pnpm test:api builds the database package and API.
The test command then runs Node’s built-in test runner.
My API test runner covers password hashing, input validation, session-token handling, cookie policy, rate limits, CSRF origin checks, authorization policy, pagination, and unauthenticated route guards.
A PostgreSQL-backed project/task workflow test runs when DATABASE_URL is configured and the schema is migrated; otherwise it is skipped.
The password-reset token lifetime and rate-limit thresholds are unspecified. The shared store for multi-instance rate limiting and production values for email-delivery settings and SESSION_COOKIE_DOMAIN are also unspecified.