xtablo-source/CLAUDE.md
2025-11-15 22:58:18 +01:00

8.6 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Common Commands

Development

pnpm install                  # Install dependencies
pnpm dev                      # Run all apps in development
pnpm dev:main                 # Run main app only (port 5173)
pnpm dev:external             # Run external booking widget (port 5174)
pnpm dev:api                  # Run API server (port 8080)

Building

pnpm build                    # Build all apps
pnpm build:apps               # Build apps only (packages are source-only)
pnpm build:staging            # Build main app for staging
pnpm build:prod               # Build main app for production

Testing

pnpm test                     # Run all tests
pnpm test:watch               # Run tests in watch mode
pnpm test:api                 # Run API tests only
cd apps/main && pnpm test     # Run tests for specific package

Quality Checks

pnpm lint                     # Check all packages with Biome
pnpm lint:fix                 # Fix linting issues
pnpm typecheck                # Type check everything
pnpm format                   # Format code

Cleanup

pnpm clean                    # Clean all build artifacts and caches

Architecture Overview

Monorepo Structure

This is a Turborepo-based monorepo with three main apps and shared packages:

  • apps/main (@xtablo/main): Primary authenticated dashboard with tablos, planning, events, chat, and notes
  • apps/external (@xtablo/external): Public booking widget (embeddable/floating modes)
  • apps/api (@xtablo/api): Hono-based REST API serving both frontend apps
  • packages/shared (@xtablo/shared): React contexts, hooks, API client, React Query setup
  • packages/ui (@xtablo/ui): Radix UI + Tailwind component library
  • packages/shared-types (@xtablo/shared-types): Pure TypeScript types (zero runtime dependencies)

Source-Only Packages

The @xtablo/shared and @xtablo/ui packages are source-only - they export TypeScript directly without a build step. Changes are instantly reflected via Vite's HMR. There's no need to rebuild or watch these packages during development.

Key Architectural Patterns

State Management

  1. React Query (TanStack Query v5): Primary tool for server state

    • 5-minute default cache time
    • Hierarchical query keys: ["tablos"], ["tablos", id], ["tablo-files", tabloId]
    • Targeted cache invalidation on mutations
  2. Zustand: Global client state, especially user context

    • User fetched via React Query, stored in Zustand for app-wide access
    • Two hooks: useUser() (throws if no session) and useMaybeUser() (returns null)

Authentication & Sessions

  • Supabase Auth with JWT tokens
  • SessionContext listens to supabase.auth.onAuthStateChange()
  • API validates JWT from Authorization header
  • Passwordless flow generates temporary accounts (is_temporary: true)
  • Protected routes use useMaybeUser() to check authentication

API Architecture

  • Framework: Hono (edge-runtime compatible)
  • Middleware Manager: Singleton pattern (initializeMiddleware() called once, reused)
  • Router Order: Public routes first → middleware applied (supabase → stream/r2/email) → authenticated routes
  • Key Routers:
    • public.ts: Unauthenticated endpoints
    • authRouter.ts: Requires authentication
    • maybeAuthRouter.ts: Optional authentication
    • tablo.ts, tablo_data.ts: Core business logic
    • stripe.ts: Payment webhooks and operations

Database & Types

  • Supabase PostgreSQL with auto-generated types
  • Generate types: npx supabase gen types typescript > packages/shared-types/src/database.types.ts
  • Type hierarchy: database.types.ts (auto-generated) → domain types (nulls removed) → API responses
  • @xtablo/shared-types: Zero-dependency package for all types
  • Frontend uses direct Supabase client: supabase.from("table").select()
  • API uses service role key to bypass RLS when needed

Data Fetching Patterns

  1. Direct Supabase queries: useQuery()supabase.from("table").select().eq(...)
  2. API calls: useQuery()api.get("/api/v1/...") with Bearer token
  3. File operations: Specialized hooks (useUploadTabloFile, useDeleteTabloFile) with automatic cache invalidation

Routing

  • Main app: Two route sets
    • publicRoutes: Auth pages, legal pages (outside UserStoreProvider)
    • routes: Protected app routes (inside UserStoreProvider)
  • Protected routes: Component checks useMaybeUser(), redirects to landing if unauthenticated
  • External app: Query params control mode (?mode=embed&eventTypeId=...)

Component Organization

  • Modals: *Modal.tsx
  • Sections: *Section.tsx
  • Cards: *Card.tsx
  • Tests co-located: *.test.tsx
  • Shared UI in @xtablo/ui
  • Business logic hooks in @xtablo/shared

External Integrations

Stream Chat

  • Chat provider wraps routes
  • Users authenticate with streamToken from API

Stripe

  • Webhooks: /api/v1/stripe-webhook
  • Sync engine keeps Supabase ↔ Stripe in sync
  • See docs/STRIPE_*.md for detailed documentation

Storage

  • Files stored in Cloudflare R2 (S3-compatible)
  • AWS S3 SDK for uploads/downloads
  • File metadata in database

Observability

  • Frontend: Datadog RUM
  • API: dd-trace for APM

Build & Deployment

Turborepo

  • Caches build outputs intelligently
  • Tasks run in parallel when possible
  • Filter specific apps: turbo build --filter=@xtablo/main

Deployments

  • Main app: Cloudflare Workers (Vite build)
  • API: Google Cloud Run (TypeScript compiled)
  • Config: Centralized in API, secrets from Google Secret Manager

Environment-Specific Builds

pnpm build:staging    # Uses .env.staging
pnpm build:prod       # Uses .env.production

Development Conventions

Query Keys

Use hierarchical naming for proper cache invalidation:

["tablos"]                    // List of tablos
["tablos", tabloId]           // Single tablo
["tablo-files", tabloId]      // Files for a tablo

Hook Patterns

All hooks return consistent shapes:

// Queries
const { data, isLoading, error } = useMyQuery()

// Mutations
const { mutate, isPending } = useMyMutation()

Error Handling

  • Errors display as toast messages via toast.add()
  • Use friendly, user-facing error messages
  • Log technical details for debugging

Loading States

Three levels of loading feedback:

  1. Route level: ProtectedRoute shows spinner
  2. Feature level: React Query isLoading
  3. Action level: Button disabled during mutation

Type Safety

  • No circular dependencies between packages
  • API only imports from @xtablo/shared-types
  • Frontend apps can import from all shared packages

Adding New Features

  1. Define types in @xtablo/shared-types or update database schema
  2. Add API endpoint in apps/api/src/routers/
  3. Create React Query hook in shared or app-specific hooks
  4. Build UI component using the hook and @xtablo/ui components
  5. Add route to apps/main/src/lib/routes.tsx if needed

Testing Strategy

API Tests

  • Vitest with test environment setup
  • Mock Supabase client for database operations
  • Test middleware and routers independently
  • See docs/API_TESTS.md and docs/MIDDLEWARE_TESTS.md

Frontend Tests

  • Vitest + React Testing Library + happy-dom
  • Test components in isolation
  • Mock React Query hooks for integration tests
  • Run with pnpm test or pnpm test:watch

Important Notes

Type Generation

After database schema changes, regenerate types:

npx supabase gen types typescript > packages/shared-types/src/database.types.ts

Cache Issues

If you encounter stale builds or weird caching:

pnpm clean
rm -rf node_modules/.cache
pnpm install
pnpm build

IDE TypeScript

If VS Code shows type errors but build works:

  • Cmd+Shift+P → "TypeScript: Restart TS Server"
  • Check pnpm typecheck passes
  • Ensure package TypeScript configs are valid

Docker Development

The project includes Docker configurations for deployment:

  • See docs/DOCKER_*.md for Docker build optimization
  • API Dockerfile uses multi-stage builds with pnpm
  • Cloud Build configurations in docs/CLOUD_BUILD_*.md

Documentation

Extensive documentation available in /docs:

  • DEVELOPMENT.md: Comprehensive development guide
  • API_*.md: API testing and integration
  • STRIPE_*.md: Stripe integration details
  • AUTH_*.md: Authentication patterns
  • DOCKER_*.md: Docker and deployment
  • CLOUD_BUILD_*.md: GCP Cloud Build setup

For questions about architecture decisions or detailed implementation notes, check the docs folder first.