This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
KidsTasky (KidTasker) — gamified family task manager. Parents assign missions, kids earn XP/stars/badges. Self-hosted, SQLite-backed, real-time via WebSockets. Also includes calendar (Google sync), shared lists, meal planning, weather, photo screensaver, and email-to-calendar magic import (Gemini AI).
pnpm dev # Start dev server (tsx + Vite middleware), http://localhost:3000
pnpm build # Build frontend (Vite) + backend (esbuild → dist/server.js)
pnpm start # Run production build (NODE_ENV=production)
pnpm test # Run all tests (vitest)
pnpm lint # Type-check only (tsc --noEmit)
# Install packages (always use pnpm — npm is blocked by preinstall guard)
pnpm add <package>
pnpm add -D <package>
# Single test file
pnpm vitest run src/server/modules/events/api.test.ts
# Single test by name
pnpm vitest run -t "should create an event"Monorepo-style single package — React SPA frontend + Express API backend in one repo, sharing TypeScript types.
- React 19 + Vite + Tailwind CSS v4 + Motion (animations)
- Entry:
src/main.tsx→src/App.tsx - Auth via JWT tokens stored in
localStorage(kidtasker_token) - Real-time updates via Socket.IO (
src/hooks/useSocket.ts) - Two role-based dashboards:
src/components/parent/andsrc/components/kid/ - Shared components in
src/components/shared/, calendar insrc/components/calendar/ - Client services in
src/services/— each wraps HTTP calls to the API - Types in
src/types.ts - Path alias:
@/maps to repo root
- Express 5 on Node 24+, entry point
server.ts - In dev mode, Vite runs as Express middleware (no separate dev server needed)
- SQLite via
better-sqlite3— in-memory (:memory:) during tests, file-based in prod - DB initialized in
src/server/db.ts, auto-runs migrations fromsrc/server/migrations/ - Migrations are numbered SQL files (e.g.,
001_init_schema.sql) - JWT auth middleware:
src/server/middleware/auth.ts - API modules:
src/server/modules/{domain}/each withroutes.tsandservice.ts- Domains: auth, users, tasks, categories, invites, notifications, rewards, events, weather, lists, meals, magic, photos, sync, settings
- All mutation routes auto-broadcast
staleDatavia Socket.IO for real-time sync - Background worker (
src/server/worker.ts) runs cron jobs for overdue task checks, Google Calendar sync, IMAP email polling
- Parent creates family → invite code → kid joins via code
- Mutations go through REST API → service layer → SQLite
- After successful mutation, middleware emits Socket.IO event → all family clients refetch
- Framework: Vitest with jsdom for frontend, supertest for API tests
- DB in tests: Always
:memory:SQLite — no file DB, no mocks - Test files: Co-located with source (
*.test.ts/*.test.tsx) - Setup:
src/setupTests.ts— mocksResizeObserverfor jsdom - API tests import
appfromserver.tsand usesupertest(app)
- Requires Node 24+ (uses native features)
.env.examplehas all config vars — key ones:JWT_SECRET,DB_PATH,GEMINI_API_KEY,GOOGLE_CLIENT_ID/SECRET- Docker: multi-stage Chainguard build, SQLite at
/data/database.dbin container - Uses pnpm everywhere (local + Docker);
pnpm-lock.yamlis the only lockfile
- Two-role system:
parentandkid— JWT payload containsuid,role,parentId parentIdis the family grouping key — all queries scope by it- Service files contain pure business logic (direct
dbcalls), route files handle HTTP - Frontend services (
src/services/) pass JWT token viaAuthorization: Bearerheader - Socket.IO rooms grouped by
parentIdfor family-scoped broadcasts