Eko — Project Context
You are assisting with Eko, a knowledge platform that builds verified, structured fact cards from multiple sources. Users learn through interactive challenges (quizzes, recall, conversational AI) powered by spaced repetition.
Core Loop
Sources → Facts → Validation → Cards → Learning
Three Content Pipelines
| Pipeline | Source | Output | Trigger |
|---|---|---|---|
| News | News APIs (NewsAPI, GNews, TheNewsAPI) | Facts from clustered articles | Cron (every 15 min) |
| Evergreen | AI generation | Timeless knowledge facts | Cron (daily) |
| Seed | Curated entries + API imports | Bootstrapped topic facts | Manual/batch |
Data Flow (6 Phases)
- Ingestion — Fetch articles → deduplicate → cluster into stories
- Extraction — AI extracts structured facts from story clusters, scored for notability
- Validation — 4-phase pipeline: structural → internal consistency → cross-model → evidence corroboration
- Challenge Generation — Pre-compute challenge content per fact across multiple styles
- Publication — Validated facts with challenge content become visible in feed
- Interaction — Users engage via card interactions with spaced repetition scheduling
Technology Stack
- Runtime: Bun, Turborepo monorepo
- Language: TypeScript, Zod schemas for all contracts
- Frontend: Next.js 16 (App Router), Tailwind v4, shadcn/ui
- Backend: Supabase (Postgres + RLS), Drizzle ORM
- Queue: Upstash Redis (11 queue types with DLQ, 3-attempt retry)
- AI: Vercel AI SDK v6 with 3-tier model routing (default/mid/high) across 7 providers
- Workers: 3 Bun queue consumers (worker-ingest, worker-facts, worker-validate)
- Billing: Stripe (Free + Eko+ plans)
- Quality: Biome (lint/format), Vitest (tests)
Monorepo Structure
apps/
web/ — Authenticated app (app.eko.day)
public/ — Marketing site (eko.day)
admin/ — Admin dashboard (admin.eko.day)
worker-ingest/ — News fetch, clustering, image resolution
worker-facts/ — AI fact extraction, evergreen, challenge content
worker-validate/ — Multi-tier fact validation
packages/
ai/ — AI model routing, fact extraction, validation
config/ — Environment configuration and model registry
db/ — Supabase client, Drizzle ORM schema
queue/ — Upstash Redis queue client
shared/ — Zod schemas, TypeScript types, entitlements
stripe/ — Stripe billing integration
ui/ — Shared UI components
System Invariants
- Fact-first — Facts are the atomic unit; everything flows from structured, schema-validated facts
- Verification before publication — No fact reaches the public feed without validation
- Source attribution — Every fact traces to source articles and validation evidence
- Schema conformance — Facts validate against
fact_record_schemas.fact_keys - Cost-bounded AI — All AI calls have model routing, budget caps, and cost tracking
- Public feed / gated detail — Feed is public; full detail requires subscription
- Topic balance — Daily quotas per topic category prevent content monoculture
AI Model Routing
Three tiers with DB-driven configuration:
- Default (~92% of calls): Cost-optimized model (currently Gemini 3 Flash Preview)
- Mid: Structure changes, complex page types, high-change scenarios
- High: Opus escalation for pricing/legal/API pages with significant changes (capped at 20/day)
Key Database Entities
stories— Clustered news articlesfact_records— Core facts with status machine (pending_validation → validated/rejected → archived)fact_record_schemas— Per-topic schema definitions (fact_keys + card_formats)fact_challenge_content— Pre-computed challenge content per fact and stylecard_interactions— User engagement with spaced repetition fieldstopic_categories— Hierarchical topic tree with daily quotasseed_entry_queue— Seeding pipeline input queue
Queue Types (11)
ingest_news, cluster_stories, extract_facts, import_facts, validate_fact, generate_evergreen, resolve_image, explode_category_entry, find_super_facts, generate_challenge_content, send_sms
When Tradeoffs Appear
Prefer: correctness > auditability > safety > cost control
Commands (always use bun, never npm/yarn/pnpm)
bun run dev— Start all appsbun run build— Build allbun run lint/bun run typecheck/bun run test— Quality checksbun run ci— Full CI validationbun run db:types— Regenerate TypeScript types from Supabase
Reel — Video Generation Platform
Reel is a standalone Tauri 2.x desktop app (/Users/jonathansteele/code/reel/) for AI-powered marketing video generation. It is the video production arm of Eko — turning Eko's verified fact cards into broadcast-quality marketing videos.
Relationship to Eko
Eko generates thousands of verified fact cards across 10 categories daily. These facts serve as source content for Reel's video pipeline. A single fact card enters Reel's Stage 1 (Extraction) and emerges from Stage 5 (Render) as a broadcast-quality marketing video ready for paid social, organic content, or product marketing.
Eko Fact Cards → Reel Extraction → Script → Visual + Audio → Render → Marketing Videos
The 5-Stage Pipeline
| Stage | Name | Service | Duration |
|---|---|---|---|
| 1 | Extraction | Gemini 2.5 Flash | ~5-15s |
| 2 | Script | Gemini 2.5 Flash | ~10-30s |
| 3 | Visual | Runway Gen-4.5 | Variable |
| 4 | Audio | ElevenLabs | Variable |
| 5 | Render | RunPod (RTX 4090) | Variable |
Stages 1-4 run locally on the desktop app. Stages 3 and 4 run in parallel. Stage 5 dispatches to a RunPod serverless worker. Intermediate assets transit through Cloudflare R2.
14 Video Styles (4 Groups)
- Narration-First (6):
narration-cinema(default),internal-dialogue,scenario-dramatization,comparison-contrast,data-storytelling,explainer-walkthrough - Short-Form (2):
product-teaser,feature-highlight-reel - UI Capture (2):
ui-demo-flow,bug-recreation-capture - Talking Head (4, require HeyGen):
talking-head-presenter,interview-testimonial,social-proof-montage,before-after-reveal
Brand Preset System
A preset is a portable directory defining a brand's entire video identity: tokens, voice configuration, voice cast, audio/visual config, prompt templates, and brand assets. Reel ships with the eko example preset.
presets/your-brand/
preset.yaml # Master brand config (id, tokens, voice_cast, defaults)
voices/ # Voice profiles per voice group
config/ # audio.yaml, visual.yaml, motion.yaml, pacing.yaml, etc.
assets/ # Logos, fonts, sounds
prompts/ # AI prompt templates for extraction and script stages
Character Studio
In-app wizard (/characters/new) for creating AI actors with consistent visual identity:
- Define Archetype — role, age range, traits, voice group
- Visual Description — archetype prompt, wardrobe, features
- Generate Anchors — 20 candidates via Flux 2 Pro, select 3-5
- Train LoRA — locks visual identity (~2-5 min, ~$1.20)
- Expand Library — generate expressions, poses, lifestyle scenes
- Map Presence — drag images to face/hands/wardrobe/environment slots
4 Voice Groups, 8 Actors:
| Voice Group | Role | Actors |
|---|---|---|
| ALEX | Primary Narrator | EKO-A01 (Founder/Visionary) |
| MAYA | Tech Professional | EKO-A02 (Analyst), EKO-A05 (Creator/Marketer) |
| JAMES | Business Executive | EKO-A03 (Manager), EKO-A06 (Small Biz Owner), EKO-A07 (Educator) |
| SOFIA | Relatable Everyperson | EKO-A04 (Young Professional), EKO-A08 (Everyday Customer) |
Eko Brand Context in Reel
The eko preset encodes the full Eko brand voice and identity:
- Brand voice: Playful, curious, wonder-driven, confident
- Core promise: "The world is full of things worth knowing."
- 10 content categories: Sports, History, Science, Culture, Records, Geography, Current Events, Technology, Animals, Art
- 8 challenge formats: Big Fan Of, Know A Lot About, Repeat After Me, Good With Dates, Degrees of Separation, Used To Work There, Partial Pictures, Originators
- Anti-pattern vocabulary: Avoid "AI", "trivia", "algorithm", "content", "consume", "users", "gamification", "curated", "engagement", "quiz" — use Eko-specific replacements instead
Tech Stack
| Layer | Technologies |
|---|---|
| Shell | Tauri 2.x (Rust backend, ~5 MB binary) |
| Frontend | React 19, Vite 6, Tailwind CSS v4, shadcn/ui |
| State | Zustand (UI) + TanStack Query (async) |
| Database | SQLite (bundled rusqlite, 10 tables) |
| AI | Gemini 2.5 Flash, Runway Gen-4.5, ElevenLabs, fal.ai |
| Rendering | RunPod (RTX 4090), Remotion, FFmpeg 6.x+ |
| Storage | Cloudflare R2 |
| Tooling | TypeScript 5.7, Biome, Vitest 3, Bun |
Key Codebase Locations
| Path | Purpose |
|---|---|
src/ | React 19 frontend (file-based routing) |
src-tauri/src/commands.rs | IPC command handlers |
src-tauri/src/db/ | SQLite schema + queries (10 tables) |
src-tauri/src/api/ | API clients (Gemini, Runway, ElevenLabs, RunPod, R2) |
src-tauri/src/pipeline/ | 5-stage pipeline orchestration |
src-tauri/src/preset/ | YAML preset loader and validator |
packages/reel-schemas/ | Shared Zod schemas (@reel/schemas) |
apps/worker-reel-render/ | RunPod serverless worker (Bun + FFmpeg) |
styles/ | 14 YAML video style definitions |
presets/eko/ | Eko brand preset |
Development Commands (always use bun)
bun tauri dev # Start Tauri app (hot reload)
bun run dev # Frontend only
bun run build # TypeCheck + Vite build
bun run test # Run all tests (Vitest)
bun run lint # Biome check (read-only)
bun run check # Biome check + auto-fix
cargo check # Type check Rust code (from src-tauri/)
Build Status
Phase 0 complete — app shell, settings, doctor checks, preset loader, 14 video styles, FFmpeg sidecar, CI, Gemini integration.
Next up: Phase 1 — Extraction and Script pipeline (Stages 1-2).
| Phase | Focus | Status |
|---|---|---|
| 0 | Shell and infrastructure | Complete |
| 1 | Extraction and Script pipeline (Stages 1-2) | Next |
| 2 | Wizard UI, API clients, Character Studio | Planned |
| 3 | Visual and Audio pipeline (Stages 3-4) | Planned |
| 4 | Remotion compositions, render pipeline, export | Planned |
| 5 | Batch system, polish, extensions | Planned |
Per-video cost: ~$0.30-0.60 at scale. Monthly cost: ~$20-82 without HeyGen.