Technical reference
Architecture, database schema, server functions, and deployment.
Architecture
TanStack Start v1 with file-based routing under src/routes/. Two layouts: _public for marketing pages and _authenticated for in-app routes (guarded by beforeLoad redirect). All app-internal server logic lives in src/lib/*.functions.ts as createServerFn calls — never edge functions.
Auth is handled by Supabase. The browser client lives in src/integrations/supabase/client.ts. Server functions use requireSupabaseAuth middleware; the bearer token is attached automatically by attachSupabaseAuth registered in src/start.ts.
Database schema
Three tables, all with RLS scoped to auth.uid():
- profiles — id (uuid, PK = auth user id), openai_api_key, anthropic_api_key, gemini_api_key, wp_url, wp_username, wp_app_password, webhook_url, google_access_token, google_token_updated_at, last_free_generation_date, unlocked_blueprints (text[]), created_at, updated_at.
- seo_generations — id, user_id, keyword, provider, payload (jsonb), created_at. Insert/select/delete only.
- memory_assets — id, user_id, name, type ('text'|'url'|'file'), raw_content, created_at.
Server functions
- seo-architect.functions.ts — runs a single generation. Input: keyword, provider, contextText, memoryId, gscProperty. Returns structured payload or FREE_LIMIT_REACHED.
- profile.functions.ts — getProfile (incl. unlocked_blueprints), updateApiKeys, updateDeliverySettings.
- generations.functions.ts — listGenerations, getGeneration, deleteGeneration, getDashboardStats.
- memory.functions.ts — listMemory, createMemory, deleteMemory.
- delivery.functions.ts + push.functions.ts — pushToWordPress, pushToWebhook.
- gsc.functions.ts — getGscProperties, getGscTopPages.
Environment & deployment
Browser env vars (Vite-replaced at build time): VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY. Server env vars (runtime, never bundled): SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, MASTER_GEMINI_KEY (freemium), Google OAuth client/secret. Read process.env inside .handler() — never at module scope.
Runtime is Cloudflare Workers (workerd) with nodejs_compat. Avoid Node-only packages, child_process, sharp, or anything requiring native bindings.