4.5 KiB
4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Build & Run Commands
pnpm install # install deps
pnpm dev # start all apps in dev mode (API :4000, Web :3000)
pnpm build # prod build all packages
pnpm lint # ESLint across all packages
pnpm typecheck # strict TypeScript checks
pnpm test # run all Vitest tests
pnpm format # Prettier format
pnpm clean # remove dist + .turbo + node_modules
Single package:
pnpm --filter @yetanother/web dev
pnpm --filter @yetanother/api dev
pnpm --filter @yetanother/api exec prisma studio
pnpm --filter @yetanother/web test:watch
pnpm --filter @yetanother/web test:e2e # Playwright
pnpm --filter @yetanother/web test -- -t "test name"
Database:
pnpm --filter @yetanother/db db:migrate # create migration
pnpm --filter @yetanother/db db:deploy # apply migrations (prod)
pnpm --filter @yetanother/db db:seed # seed dev data
pnpm --filter @yetanother/db exec prisma generate # regen Prisma client
Desktop (Tauri v2, requires Rust):
cd apps/desktop && pnpm tauri dev
cd apps/desktop && pnpm tauri build
Infra:
docker compose up -d postgres redis meilisearch
docker compose up --build # full prod build
Tech Stack
- Monorepo: Turborepo + pnpm workspaces (pnpm 11+)
- Frontend: React 19 + TypeScript strict, Vite 6, Tailwind CSS 4, shadcn/ui-style (Radix primitives)
- State: Zustand (global stores), TanStack React Query (server), Jotai (local UI), react-router-dom v7
- Editor: TipTap / ProseMirror (block-based with tables, task lists, code blocks, slash menu)
- Backend: Fastify 5, Prisma ORM + PostgreSQL 16 (pgvector), Redis (ioredis), Zod validation
- Real-time: Yjs (CRDT) + WebSocket (fastify-websocket), y-prosemirror, y-indexeddb
- Search: Meilisearch (full-text) + pgvector (semantic embeddings)
- API: REST (under
/api/v1/) + GraphQL (Mercurius at/graphql) - Desktop: Tauri v2 (Rust)
- Testing: Vitest + React Testing Library + jsdom, Playwright (E2E)
- i18n: i18next + react-i18next
- Auth: JWT (fastify-jwt) with refresh tokens, bcryptjs
Architecture
Monorepo layout
apps/
api/ — Fastify server (REST + GraphQL + WebSocket)
web/ — React SPA (Vite, Tailwind, TipTap editor)
desktop/ — Tauri wrapper around web app
mobile/ — React Native (not started)
packages/
db/ — Prisma schema + client, seed data
types/ — Zod schemas + TypeScript types (shared frontend/backend)
ui/ — Radix-based component library (button, dialog, tabs, toast, tooltip)
hooks/ — Shared React hooks (useDebounce, useLocalStorage, useMediaQuery)
utils/ — Shared utilities (cn, constants)
tooling/
eslint/ — Shared ESLint configs (base, node, react)
typescript/ — Shared TS configs (base, node, react)
Data model (Node-based)
Everything is a Node — tasks, events, notes, projects, goals share a unified schema. Nodes have polymorphic types, parent/child hierarchies, typed links (references, blocks, relates_to, etc.), tags, and version-based optimistic concurrency. Embeddings store pgvector vectors for semantic search.
API patterns
- Routes registered in
apps/api/src/main.tsunder/api/v1prefix - Auth via JWT with refresh token rotation (cookie + bearer)
- Route handlers:
app.get('/nodes', async (request) => { ... })withapp.prismadecorator - Zod body validation inline in route files
- Background: Meilisearch indexing + activity logging fire-and-forget (.catch(() => {}))
- Error handling:
AppErrorclass +handleErrorhelper (Zod errors → 400, AppError → statusCode, else → 500)
Frontend patterns
- Zustand stores for UI state (stores/notes.ts, stores/tasks.ts, stores/calendar.ts)
- API client in
lib/api.tswith auto-refresh on 401 - TipTap editor with custom extensions, toolbar, slash menu
- React.lazy route splitting for notes/tasks/calendar pages
- Calendar: drag-and-drop events, multi-view (day/week/month), event dialog
- Tasks: drag-and-drop reorder (dnd-kit), views (list/board/timeline), NL date parsing (chrono-node)
Key constraints
- All objects belong to a workspace (multi-tenant via workspaceId)
- Soft delete via
status: 'deleted'on nodes - Optimistic concurrency on node updates via
versionfield - Pre-commit: Husky runs lint-staged (ESLint + Prettier)
- Commit style: conventional commits (
feat:,fix:,refactor:, etc.)