Upload a book. Get AI-powered character tracking, page discussions, concept analysis, and generated illustrations. Billed at cost.
- Book reader — paginated reading view (CSS columns layout) with arrow-key navigation, reading progress, and bookmarks
- Character panel — automatic extraction, relationship mapping, summary history timeline, image generation
- Structure panel — concepts, themes, and plot structure tracked across pages
- Chat — ask questions about any page with full context
- Image generation — generate illustrations for characters, scenes, or concepts; toggle inline in reader
- Billing — usage-based Stripe metered billing at 2× API cost, reported weekly
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, Tailwind CSS, Supabase Auth |
| Backend API | Flask (Python) |
| Database | PostgreSQL via Supabase |
| Edge Functions | Supabase (Deno) |
| Storage | Supabase Storage |
| Billing | Stripe metered billing |
| Secrets | TempleDB (age-key encrypted) |
| Deploy | TempleDB deploy hooks |
- TempleDB installed and on PATH
- Node.js 18+, Python 3.11+
- A Supabase project
# Supabase
templedb secret set bza NEXT_PUBLIC_SUPABASE_URL https://<ref>.supabase.co --keys age-key
templedb secret set bza NEXT_PUBLIC_SUPABASE_ANON_KEY <anon-key> --keys age-key
templedb secret set bza SUPABASE_URL https://<ref>.supabase.co --keys age-key
templedb secret set bza SUPABASE_ANON_KEY <anon-key> --keys age-key
templedb secret set bza SUPABASE_SERVICE_ROLE_KEY <service-role-key> --keys age-key
templedb secret set bza SUPABASE_DB_PASSWORD <db-password> --keys age-key
templedb secret set bza SUPABASE_DB_HOST aws-1-us-east-1.pooler.supabase.com --keys age-key
# AI
templedb secret set bza OPENAI_API_KEY sk-... --keys age-key
# Stripe (use placeholders until ready; run setup-stripe.sh to populate)
templedb secret set bza STRIPE_SECRET_KEY sk_live_... --keys age-key
templedb secret set bza NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY pk_live_... --keys age-key
# App
templedb secret set bza SITE_URL https://yourdomain.com --keys age-key./scripts/db-migrate.sh # runs all migrations in supabase/setup/ in order
./scripts/db-migrate.sh --list # list migration files
./scripts/db-migrate.sh 08 # run a specific migration by partial name./scripts/setup-stripe.shCreates the product, meter, price, and webhook endpoint in Stripe. Stores all resulting IDs back in TempleDB automatically.
templedb deploy run bza # full stack (local target)
templedb deploy run bza --target productionThe deploy hook (deploy_bza_web.sh) injects secrets, deploys edge functions, starts the Next.js frontend, then starts the Flask backend.
# Frontend only
cd frontend && npm run dev
# Frontend + Supabase edge functions served locally
cd frontend && npm run dev:all
# Update a secret and redeploy
templedb secret set bza STRIPE_SECRET_KEY sk_live_... --keys age-key
templedb deploy run bzabza/
├── frontend/ Next.js SaaS frontend
│ ├── app/ Pages (dashboard, billing, reader, auth)
│ ├── components/ BookReader, CharacterPanel, StructurePanel, ImagePanel, …
│ └── lib/ supabase-queries.ts, localStorage.ts
├── backend/ Flask API (book processing, analysis queue)
├── supabase/
│ ├── functions/ Edge functions (analyze-characters, chat-with-book, …)
│ ├── setup/ SQL migrations — run via scripts/db-migrate.sh
│ └── .env.template Documents required edge function env vars (no real values)
└── scripts/
├── db-migrate.sh Run SQL migrations against production DB
├── setup-stripe.sh One-time Stripe object creation
└── report-usage.sh Weekly usage reporting to Stripe meter
API costs are recorded per request in api_usage. Every Sunday a cron job sums each customer's raw cost, multiplies by 2, converts to cents, and sends a Stripe meter event (ai_usage_cents). Stripe invoices at $0.01/unit on a daily interval.
# Add to crontab
0 0 * * 0 /tmp/bza/scripts/report-usage.sh >> /tmp/bza/logs/usage.log 2>&1
# Dry run (prints without sending to Stripe)
./scripts/report-usage.sh --dry-runAll secrets live in TempleDB encrypted with age-key. No .env files with real values are committed. The files below are generated at deploy/dev time and gitignored:
frontend/.env.local— Next.js environment variablessupabase/.env— edge function environment variables
templedb secret list bza # list all
templedb secret get bza KEY # read one
templedb secret set bza KEY value --keys age-key # set one
templedb secret export bza --format dotenv # export all