253 lines
8.6 KiB
Markdown
253 lines
8.6 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Common Commands
|
|
|
|
### Development
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
```bash
|
|
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
|
|
```bash
|
|
pnpm lint # Check all packages with Biome
|
|
pnpm lint:fix # Fix linting issues
|
|
pnpm typecheck # Type check everything
|
|
pnpm format # Format code
|
|
```
|
|
|
|
### Cleanup
|
|
```bash
|
|
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
|
|
```bash
|
|
pnpm build:staging # Uses .env.staging
|
|
pnpm build:prod # Uses .env.production
|
|
```
|
|
|
|
## Development Conventions
|
|
|
|
### Query Keys
|
|
Use hierarchical naming for proper cache invalidation:
|
|
```typescript
|
|
["tablos"] // List of tablos
|
|
["tablos", tabloId] // Single tablo
|
|
["tablo-files", tabloId] // Files for a tablo
|
|
```
|
|
|
|
### Hook Patterns
|
|
All hooks return consistent shapes:
|
|
```typescript
|
|
// 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:
|
|
```bash
|
|
npx supabase gen types typescript > packages/shared-types/src/database.types.ts
|
|
```
|
|
|
|
### Cache Issues
|
|
If you encounter stale builds or weird caching:
|
|
```bash
|
|
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.
|