Architecture

Stack: TanStack Start (React 19, Vite 7) on Cloudflare Workers · Tailwind v4 · Lovable Cloud (Supabase) · Lovable AI Gateway · ElevenLabs Conversational AI

Layers

┌─────────────────────────────────────────────────────┐
│  Browser — React 19 / TanStack Router               │
│  • Ritual UI (index.tsx)                            │
│  • SVG visualizers (HexagramGlyph, ZodiacWheel)     │
│  • ElevenLabs WebRTC client (@elevenlabs/react)     │
│  • localStorage: birthdate, session history         │
└──────────────┬──────────────────────────────────────┘
               │ RPC (createServerFn) + fetch
               ▼
┌─────────────────────────────────────────────────────┐
│  Cloudflare Worker — TanStack Start SSR             │
│  • src/lib/*.functions.ts  (server functions)       │
│    - divination · interpret · sigil · vision        │
│    - astrology · elevenlabs token route             │
│  • Middleware: requireSupabaseAuth (RLS as user)    │
└─────┬─────────────────┬──────────────┬──────────────┘
      │                 │              │
      ▼                 ▼              ▼
┌───────────┐    ┌──────────────┐  ┌────────────────┐
│ Supabase  │    │ Lovable AI   │  │ ElevenLabs API │
│ Postgres  │    │ Gateway      │  │ • WebRTC token │
│ + Storage │    │ • Gemini     │  │ • Voice agent  │
│ + Auth    │    │   text/img   │  │   (WebRTC)     │
│ (anon +   │    │ • GPT-Image  │  └────────────────┘
│  RLS)     │    └──────────────┘
└───────────┘

Frontend

  • Routing: file-based (src/routes/), single ritual page at /.
  • State: local React state + localStorage for birthdate, history arc, sigil intent.
  • Visualizers: hand-rolled SVG — Rider-Waite-Smith images for tarot, procedural hexagrams with changing-line indicators, zodiac wheel for horoscope, deterministic seeded sigil geometry.
  • Voice: @elevenlabs/react useConversation over WebRTC; live sendContextualUpdate pushes the full altar state (cards, sigil, vision, horoscope, history, birthdate) to the agent on every change.

Backend (server functions) All app logic is createServerFn in src/lib/*.functions.ts — typed RPC, no REST layer:

  • divination.functions.ts — Fisher–Yates tarot shuffle, 3-coin I Ching cast, seeded RNG on the server.
  • interpret.functions.ts — Gemini call for per-position significance + full-reading synthesis, birthdate-aware, history-aware.
  • astrology.functions.ts — natal + transit Sun/Moon calc, timeframe-scoped horoscope.
  • sigil.functions.ts — chaos-magic reduction → seeded SVG seal → Gemini image ornamentation → Supabase Storage.
  • vision.functions.ts — GPT-Image symbolic scene from the drawn cards.
  • routes/api/elevenlabs/token.ts — mints WebRTC conversation tokens with ELEVENLABS_API_KEY + ELEVENLABS_AGENT_ID.

Data

  • Postgres: symbols (78 tarot + 64 hexagrams), spreads, sessions, readings, sigils, visions, uploads.
  • RLS: every table locked to auth.uid(); anonymous sign-in on page load gives each visitor a scoped identity.
  • Storage: private buckets sigils, visions, uploads; signed URLs returned by server functions.

AI

  • Text/interpretation: Lovable AI Gateway → google/gemini-*-flash (chat completions).
  • Images: Gateway → google/gemini-3.1-flash-image (sigil ornament) and openai/gpt-image-2 (visions).
  • Voice: ElevenLabs Conversational AI agent, configured server-side by agent ID.

Key patterns

  • Isomorphic loaders, server-only secrets — process.env reads only inside .handler() bodies.
  • Context streaming, not tool calling — the voice agent sees the whole altar via sendContextualUpdate, so no tool round-trips.
  • Deterministic seeded generation — FNV-1a + Mulberry32 makes sigils reproducible per intent while still varied.
  • Session arc as prompt fuel — prior readings are re-injected into every new interpretation so the narrative compounds.

Built With

  • claude
  • lovable
  • supabase
Share this project:

Updates