๐ข System Health
System Overview
Jorrii Spark is a kid-first AI creativity platform for ages 6-12 with a Pixar-inspired bubbly design. Kids can create images, videos, music, sounds, and multi-step projects using safe, curated AI tools โ all managed by a parent dashboard.
Core Concept
Parents sign up with Google or email โ create kid accounts with PINs โ kids log in with their PIN โ create content within plan limits โ parents review everything from the dashboard.
๐ Business Dashboard
Architecture
Tech Stack
| Layer | Technology | Details |
|---|---|---|
| Frontend | Static HTML/CSS/JS | Hosted on Hostinger, no framework |
| Auth & DB | Supabase | Google OAuth, email/password, Row Level Security |
| API | AWS API Gateway + Lambda | Shared with adult Jorrii backend |
| Storage | AWS S3 + CloudFront | Generated images, videos, audio files |
| Database | Supabase PostgreSQL + DynamoDB | Users/kids in Supabase, generations in DynamoDB |
| Fonts | Google Fonts | Fredoka (headings), Quicksand (body) |
Domain & Hosting
| What | Where |
|---|---|
| Domain | jorrii.io |
| Hosting | Hostinger (static files) |
| Supabase Project | cwudeohugaraangftkfz.supabase.co |
| API Endpoint (Adult) | xm35vp0qoh.execute-api.us-east-2.amazonaws.com |
| API Endpoint (Kids/Spark) | ymf072zyfd.execute-api.us-east-2.amazonaws.com |
Pages & Status
| Page | File | Status | Notes |
|---|---|---|---|
| Homepage | index.html | Done | Hero, showcase, tools, safety, footer. Links updated. |
| Parent Login | parent-login.html | Done | Split layout: video + login. Google OAuth working (PKCE). |
| Parent Dashboard | parent-dashboard.html | Done | Plan, kids, usage, creations, quick actions. |
| Kid PIN Login | kid-pin.html | Done | Fullscreen video + arcade numpad + confetti. Redirects to kid-dashboard. |
| Kid Dashboard | kid-dashboard.html | Done | Welcome banner, usage bars, quick tools, recent creations. No pricing/admin. |
| Pricing | pricing.html | Done | 5 tiers with toggle monthly/yearly, feature comparison. |
| Make a Picture | make-a-picture.html | Done | 3-panel layout. 6 real models (GPT Image 1, Gemini Imagen 3, Flux, Recraft, Ideogram, Nano Banana). Character Look picker (skin/hair/extras). Style chips. Ratio selector. Reference image upload โ when uploaded, routes to /api/edit-image (GPT image edit, identity-preserving). New: "Pick from My Creations" gallery picker โ select any previously generated image as reference without downloading. Completion sound. Auto-save to gallery. Lambda routes: /api/generate-image, /api/edit-image. |
| Edit a Picture | edit-a-picture.html | Done | Upload or pick image from gallery โ text prompt โ GPT Image Edit (gpt-image-1) โ inpainting/editing. Auto-save to gallery. Full kid auth + completion sound. |
| Make a Video | make-a-video.html | Done | 3-panel layout, purple theme. Two modes: Text-to-Video (t2v) and Image-to-Video (i2v). T2V models: Hailuo-2, Seedance, Veo 3 Fast, Veo 3.1, Veo 3.1 Fast, Kling 3. I2V models: Hailuo-2, Kling 3, Luma Photon, Veo 3.1 โ all routed to /api/anchored-video for identity-locked animation (preserves person's face/appearance). I2V image picker has two tabs: My Creations (gallery) and Upload. Motion chips, duration selector, ratio selector, video loader overlay with ETA. Completion sound. Auto-save to gallery. Lambda routes: /api/kling-video (t2v), /api/anchored-video + /api/process-anchored-video (i2v). |
| ๐บ Magic Move | motion-control.html | Done | Upload character photo + dance video โ Kling v2.6 Motion Control (Replicate). Presigned S3 upload for video (bypasses Lambda payload limit). Fast/Pro mode, Short/Long orientation, scene chips, keep-sound toggle. Full loader overlay. Auto-save to gallery. Lambda routes: /api/get-upload-url, /api/kling-motion, /api/process-kling-motion. S3 CORS policy added. |
| Edit a Picture | edit-a-picture.html | Done | Upload or pick image from gallery โ text prompt โ GPT Image Edit (gpt-image-1) โ inpainting/editing. Auto-save to gallery. Full kid auth + completion sound. |
| Make a Video | make-a-video.html | Done | 3-panel layout, purple theme. Two modes: Text-to-Video (t2v) and Image-to-Video (i2v). T2V models: Hailuo-2, Seedance, Veo 3 Fast, Veo 3.1, Veo 3.1 Fast, Kling 3. I2V models: Hailuo-2, Kling 3, Luma Photon, Veo 3.1 โ all routed to /api/anchored-video for identity-locked animation (preserves person's face/appearance). I2V image picker has two tabs: My Creations (gallery) and Upload. Motion chips, duration selector, ratio selector, video loader overlay with ETA. Completion sound. Auto-save to gallery. Lambda routes: /api/kling-video (t2v), /api/anchored-video + /api/process-anchored-video (i2v). |
| ๐บ Magic Move | motion-control.html | Done | Upload character photo + dance video โ Kling v2.6 Motion Control (Replicate). Presigned S3 upload for video (bypasses Lambda payload limit). Fast/Pro mode, Short/Long orientation, scene chips, keep-sound toggle. Full loader overlay. Auto-save to gallery. Lambda routes: /api/get-upload-url, /api/kling-motion, /api/process-kling-motion. S3 CORS policy added. |
| Make Sounds | make-sounds.html | Done | 3 tabs: Voice (9 presets + custom ElevenLabs ID), SFX (9 quick picks), Music (9 genres). Completion sound effects per type. |
| Make It Talk (redirect) | make-it-talk.html | Redirect | Redirects to make-sounds.html?tab=voice |
| Make Music (redirect) | make-music.html | Redirect | Redirects to make-sounds.html?tab=music |
| My Creations | my-creations.html | Done | Gallery with filter bar (images, videos, voices, music, books, movies), lightbox, flipbook reader for books, video player for movies, share-to-showcase. |
| Showcase | showcase.html | Done | Public gallery of shared creations. Nav links updated with Book Maker + Movie Maker. |
| Spark Studio | spark-studio.html | Disabled | Visual node pipeline UI โ currently disabled/not linked from nav. API endpoints not fully connected. |
| Spark Lab | spark-lab.html | Done | Prompt builder with category suggestions. ๐ค Character Builder panel (person, age, skin tone, hair, color, build, extras). Random prompt dice. Send-to-tool routing. |
| Spark Missions | spark-missions.html | Done | Guided tutorials for kids. Nav links updated with Book Maker + Movie Maker. |
| Book Maker | book-maker.html | Done | 8-page storybook wizard with full Character Builder (person/age/skin/hair/personality/extras), setting/adventure/ending/art-style โ GPT-4o โ per-page images โ flipbook viewer โ PDF export โ Save to Gallery via /api/save-book. Completion sound. |
| Make a Game | make-a-game.html | Done | Spark Game Studio hub โ two-track selector: ๐ Python Curriculum (7-lesson path) and โก Quick Build (AI-generated game). Links to game-quickbuild.html and game-curriculum.html (curriculum coming soon). Hero stats, game type cards, How It Works steps. Full sidebar + mobile menu. |
| Game Quick Build | game-quickbuild.html | Done | 4-step wizard with visual asset pickers: Step 2 shows 7 hero cards (Zara/Nova/Lyra/Blaze/Finn/Koa/Sparky) with real images from /game-assets/. Step 3 shows 7 world background cards. GPT-4o generates self-contained HTML5 canvas game with real assets loaded via new Image(). Keyboard forwarding from parent page into iframe via event dispatch + 50ms key-state sync + explicit R key handler. CORS fixed on both API gateways. Background scrolling + camera follow for platformer. Save + Publish buttons wired to POST /api/save-game. |
| My Games | my-games.html | Done | Personal game gallery: filter by game type, game cards with type icon + date, fullscreen iframe play modal (fetches code from S3 via /api/get-game-code), publish/unpublish toggle, delete. Works for both parent and kid sessions. Embedded sidebar CSS. |
| Games Showcase | games-showcase.html | Done | Public community gallery: hero with live stats (total games, unique creators), featured game card, search bar, game type filter chips, grid of all published games. Play modal with iframe. Calls GET /api/get-showcase-games. No auth required to browse. |
| Code Quest | game-curriculum.html | Done | 7-lesson Python curriculum with embedded Skulpt editor. Dashboard view (lesson map with XP bar, progress stats, node states: done/current/locked/ai-unlock). Lesson detail view (concept explanation, syntax-highlighted examples, live Python editor via Skulpt, challenge validator, hint button). Progress saved to Supabase code_quest_progress table. Confetti + XP on completion. Lessons 5โ6 link to Make a Picture / Make Sounds. Lesson 7 finale links to Make a Game. |
| Movie Maker | movie-maker.html | Done | Storyboard editor: 5 clip sources (My Videos, ๐บ Magic Move, My Images, upload, title cards), 4 transitions (cut/fade/slide-left/slide-right), background music, sound effects track with timestamps, preview player, Canvas+MediaRecorder export โ auto-save to gallery via /api/save-movie. Completion sound. Nav updated with Edit a Picture + Magic Move sidebar links. |
| Lip Sync | lip-sync.html | Disabled | 4 modes: Sing (character + song lyrics โ TTS โ lip sync), Talk (character + typed text โ TTS โ lip sync), Animate (upload face + audio โ lip sync), Record (upload face + mic recording โ lip sync). 7 character presets (robot, princess, alien, wizard, monster, fairy, dino) hosted at jorrii.io/character/. 3 Replicate models: SadTalker, Wav2Lip, LivePortrait. Auto-save to gallery, share to showcase. Uses /api/generate-lipsync (async) + /api/voice for TTS. |
| Disclosures | disclosures.html | TODO | Legal disclosures page. Footer link added. |
| Admin Docs | admin.html | Done | This page โ now with live business dashboard. |
Supabase Setup
Project Details
- Project URL:
https://cwudeohugaraangftkfz.supabase.co - Anon Key:
eyJhbGciOiJIUzI1NiI...DOTr-sHSacxw7r...(truncated) - Region: US East
- Auth Providers: Google OAuth, Email/Password
Important: Separate from Adult Jorrii
This is a separate Supabase project from the adult Jorrii site. They share the same AWS API backend but have independent auth systems and databases.
Database Schema
kids table
CREATE TABLE kids (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
parent_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
pin TEXT NOT NULL,
avatar INTEGER DEFAULT 1,
created_at TIMESTAMPTZ DEFAULT now()
);
-- RLS Policies
"Parents see own kids" โ SELECT WHERE parent_id = auth.uid()
"Parents add own kids" โ INSERT WITH CHECK parent_id = auth.uid()
"Parents update own kids" โ UPDATE WHERE parent_id = auth.uid()
"Parents delete own kids" โ DELETE WHERE parent_id = auth.uid()
"Anyone can verify PIN" โ SELECT WHERE true (for kid login)
subscriptions table
CREATE TABLE subscriptions (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
parent_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
plan TEXT NOT NULL DEFAULT 'spark',
status TEXT NOT NULL DEFAULT 'active',
billing TEXT DEFAULT 'monthly',
stripe_id TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
expires_at TIMESTAMPTZ
);
-- Plans: spark (free), glow, blaze, supernova, infinite
-- Status: active, cancelled, trialing, expired
usage_tracking table
CREATE TABLE usage_tracking (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
parent_id UUID NOT NULL REFERENCES auth.users(id),
type TEXT NOT NULL, -- image, video, voice, sfx, music
date DATE NOT NULL DEFAULT CURRENT_DATE,
count INTEGER DEFAULT 0,
UNIQUE(parent_id, type, date)
);
-- Helper functions:
-- check_usage(p_parent_id, p_type) โ {allowed, remaining, limit}
-- increment_usage(p_parent_id, p_type) โ increments daily count
gallery_items table (MIGRATED to DynamoDB)
-- Supabase gallery_items is NO LONGER USED for storage.
-- Gallery data is now in DynamoDB: spark-gallery
-- DynamoDB Key: userId (HASH) + createdAt (RANGE)
-- GSI: isPublic-createdAt-index (for Showcase)
-- S3 Bucket: jorrii-spark-creations (public read)
-- S3 Temp: jorrii-spark-jobs-output (1-day TTL)
-- Lambda: jorrii-spark-api (auto-saves on generation)
-- API endpoints: /api/gallery, /api/gallery/share, /api/showcase
-- Supabase tables STILL ACTIVE:
-- subscriptions, kids, usage_tracking (check_usage/increment_usage)
-- generation_log (logging only)
generation_log table
CREATE TABLE generation_log (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
parent_id UUID REFERENCES auth.users(id),
kid_id UUID REFERENCES kids(id),
type TEXT NOT NULL,
model TEXT,
prompt TEXT,
status TEXT DEFAULT 'completed',
file_url TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
plan_limits view
-- View that returns daily limits per plan per type
-- Used by check_usage() function
-- Plans: spark โ glow โ blaze โ supernova โ infinite
-- Types: image, video, voice, sfx, music
Authentication
Parent Auth (Supabase)
Resolved: OAuth Redirect Loop
Google OAuth redirect loop was caused by PKCE code exchange failing silently. Fixed by using flowType: 'pkce' in Supabase client config and ensuring correct redirect URIs in Google Cloud Console.
Status: โ Fixed and working.
Kid Auth (PIN-based)
Kid sessions are stored in sessionStorage (not Supabase auth). This means kid sessions don't persist across tabs or browser restarts โ this is intentional for safety.
Supabase URL Configuration
| Setting | Value |
|---|---|
| Site URL | https://jorrii.io |
| Redirect URLs | https://jorrii.io/parent-login.htmlhttps://jorrii.io/parent-dashboard.html |
Google OAuth Config
| Setting | Value |
|---|---|
| Google Cloud Project | tots2025 |
| Authorized Redirect URI | https://cwudeohugaraangftkfz.supabase.co/auth/v1/callback |
| Client ID & Secret | Stored in Supabase โ Authentication โ Providers โ Google |
API / Backend
Shared Backend
Jorrii Spark shares the same AWS backend as the adult Jorrii site:
- API Gateway (Adult):
xm35vp0qoh.execute-api.us-east-2.amazonaws.comโ Lambdajorrii-api - API Gateway (Kids/Spark):
ymf072zyfd.execute-api.us-east-2.amazonaws.comโ Lambdajorrii-spark-api - DynamoDB Tables:
spark-jobs(job queue),spark-gallery(gallery metadata) - S3 Buckets:
jorrii-spark-creations(public gallery files),jorrii-spark-jobs-output(temp job files) - Lambda functions handle generation requests
- DynamoDB stores generation history
- S3 + CloudFront serve generated files
Endpoints Used (Spark API โ ymf072zyfd)
| Endpoint | Method | Purpose | Payload |
|---|---|---|---|
| ๐จ Images (async โ poll /api/check-job) | |||
/api/generate-image | POST | GPT Image 1 generation (async โ poll /api/check-job) | {prompt, size, quality, count, model} |
/api/edit-image | POST | GPT Image 1 edit โ preserves identity/appearance from reference photo. Used by make-a-picture when a reference image is uploaded. Synchronous โ returns output URL directly, no polling needed. | {image (base64), imageType, prompt, size} |
/api/nano-banana | POST | Gemini Image generation | {prompt} |
/api/flux-schnell | POST | Flux Schnell (Replicate) | {prompt} |
/api/sd35 | POST | Stable Diffusion 3.5 Large | {prompt} |
/api/recraft | POST | Recraft v3 | {prompt} |
| ๐ฌ Videos (async โ poll /api/check-job) | |||
/api/text-to-video | POST | Wan 2.1 video (Replicate) | {prompt, aspect_ratio} |
/api/kling-video | POST | Kling / Hailuo / Veo / Luma text-to-video (Replicate) | {prompt, aspect_ratio, duration, model, start_image?} |
/api/anchored-video | POST | Identity-locked image-to-video โ animates uploaded photo without changing the person's appearance. Supports hailuo-2, kling-3, luma-photon, veo-3.1, seedance. | {prompt, image (base64), imageType, model, duration?, aspect_ratio?} |
/api/process-anchored-video | POST | Internal async processor for anchored-video (self-invoked by Lambda) | {jobId, prompt, imageUrl, model, duration, aspect_ratio, parentId, kidId, kidName} |
| ๐ Audio | |||
/api/voice | POST | TTS via OpenAI (synchronous) | {text, voice} |
/api/elevenlabs-sfx | POST | Sound effects via ElevenLabs (synchronous) | {text, duration_seconds} |
/api/music | POST | Music via MusicGen (async โ poll) | {prompt, duration} |
/api/audiobook | POST | Narration via Kokoro TTS (async) | {text, voice, speed} |
| ๐ Books | |||
/api/save-game | POST | Saves completed game HTML to S3 (jorrii-jobs-output) and writes gallery entry (type=game) to DynamoDB. Supports published flag for showcase. Registered on xm35vp0qoh. | |
/api/get-games | GET | Fetches user's saved games from gallery table filtered by type=game. Supports ?userId and ?kidId params. Returns array without gameCode (code fetched separately). | |
/api/get-game-code | POST | Fetches full HTML game code from S3 for a specific game (by userId + createdAt). Used by play modal in My Games and Games Showcase. | |
/api/get-showcase-games | GET | Returns all published games (type=game, isPublic=true) via GSI. Public endpoint โ no auth required. Used by games-showcase.html. | |
/api/generate-game | POST | Starts async game generation job via GPT-4o. Returns jobId. Registered on xm35vp0qoh (jorrii-api Lambda). Supports: platformer, catch, quiz, maze. Game types injected into tailored prompts. | |
/api/generate-story | POST | Generate 8-page storybook (async) | {character, setting, adventure, ending, artStyle} |
/api/save-book | POST | Save complete book to gallery (async) | {bookData (JSON string of title + pages)} |
| ๐๏ธ Movies | |||
/api/save-movie | POST | Save exported movie to gallery (async) | {data (base64 video), title} |
| ๐ Lip Sync | |||
/api/generate-lipsync | POST | Lip sync video generation (async โ poll /api/check-job). Supports 3 Replicate models: SadTalker (a519cc0c), Wav2Lip (8d65e3f4), LivePortrait (067dd98c). Face input via character name โ jorrii.io/character/{name}.png or user-uploaded image โ S3 temp. Audio input via audioUrl or base64 audioData โ S3 temp. | {character|faceImage, audioUrl|audioData, model, mode} |
| ๐ผ๏ธ Gallery & Showcase | |||
/api/gallery | POST | List: {_action:"list"} ยท Delete: {_action:"delete", createdAt} | + X-Parent-Id header |
/api/gallery/share | POST | Toggle public sharing on gallery item | {createdAt (Number), isPublic (bool)} |
/api/showcase | GET | Public gallery (GSI: isPublic-createdAt-index) | ?limit=50&type=image |
/api/check-job | POST | Poll async job status | {jobId} |
/api/health | POST | Health check โ returns API key status | โ |
Async Generation Flow (Images, Videos, Music, Books, Save-Book, Save-Movie)
1. POST to endpoint (e.g. /api/generate-image, /api/text-to-video, /api/save-book) โ returns {jobId, status:"processing"}
2. Poll /api/check-job every 3 seconds โ returns {jobId, status, output} when done
3. output contains base64 data URI or file URL
4. Lambda auto-saves to DynamoDB spark-gallery + S3 jorrii-spark-creations
5. Auth via X-Parent-Id + optional X-Kid-Id / X-Kid-Name headers
Synchronous Endpoints (Voice, SFX)
/api/voice and /api/elevenlabs-sfx return immediately with {output: "data:audio/mpeg;base64,..."}. No polling needed. Lambda auto-saves to gallery.
Error Codes (Kid-Friendly via sanitizeError)
E101 โ Quota exhausted ยท E102 โ Rate limited ยท E103 โ Billing/model unavailable
E202 โ API key not configured ยท E301 โ Model not found ยท E302 โ Timeout
E303 โ No output returned ยท E401 โ Safety filter blocked prompt
E402 โ Invalid request ยท E500 โ Unknown error (includes actual error message for debugging)
Book Maker Story Generation Flow
1. POST to /api/generate-story with character, setting, adventure, ending, artStyle
2. Lambda doGenerateStory() calls GPT-4o with system prompt โ returns 8-page JSON
3. Each page has text (1-2 sentences, max 25 words) and imagePrompt
4. Image prompts begin with consistent character description for visual continuity
5. Frontend then generates images for each page via /api/generate-image
6. Uses string concatenation (not template literals) to avoid Lambda escaping issues
Design System
Colors
| Name | Hex | Usage |
|---|---|---|
| Spark Teal | #44D5DC | Primary accent, glow lines, CTAs |
| Spark Purple | #A78BFA | Secondary accent, kid pin, sidebar |
| Deep Purple | #7C3AED | Buttons, headings, links |
| Spark Pink | #F9A8D4 | Music, accents |
| Spark Orange | #FDBA74 | Sounds, warnings |
| Spark Blue | #7DD3FC | Studio, info |
Typography
| Font | Weight | Usage |
|---|---|---|
| Fredoka | 500-700 | All headings, buttons, labels, nav |
| Quicksand | 400-600 | Body text, descriptions, inputs |
Shared CSS
All pages (except kid-pin.html and parent-login.html) import spark-styles.css which contains the top nav, sidebar, footer, and base styles. Always cache-bust with ?v=N.
Key Sizing
| Element | Size |
|---|---|
| Nav height | 72px |
| Sidebar width | 180px |
| Nav logo | 56px height |
| Sidebar icons | 38px |
| Tool card icons | 80% width, max 140px |
| Safety/Parent card icons | 70% width, max 120px |
| How It Works circles | 140px |
Icon Assets
All custom icons are in the images/ folder. Created in Photoshop at 792ร792px (11ร11 inches at 72ppi).
Sidebar Icons
| File | Label | Fallback Emoji |
|---|---|---|
picture1.png | Make a Picture | ๐จ |
video1.png | Make a Video | ๐ฌ |
music1.png | Make Music | ๐ต |
sound1.png | Make Sounds | ๐ |
studio1.png | Spark Studio | โก |
creation1.png | My Creations | ๐ผ๏ธ |
Section Icons
| File | Section |
|---|---|
picture.png | Tool cards โ Make a Picture |
video.png | Tool cards โ Make a Video |
music.png | Tool cards โ Make Music |
sound.png | Tool cards โ Make Sounds |
sparkstudio.png | Tool cards โ Spark Studio |
think.png | How It Works โ Step 1 |
makeit.png | How It Works โ Step 2 |
sparkit.png | How It Works โ Step 3 |
kidsafe.png | Safety โ Kid Safe |
prompts.png | Safety โ Smart Prompts |
content.png | Safety โ Content Filters |
notsocial.png | Safety โ Not Social |
learn.png | Parents โ Learn |
classroom.png | Parents โ Classroom |
parent.png | Parents โ Controls |
positive.png | Parents โ Positive |
signin1.png | Sign In button icon |
pin1.png | Kid PIN button icon |
Videos
| File | Page | Format |
|---|---|---|
videos/roller.mp4 | Homepage banner | 16:9 |
videos/login.mp4 | Parent login (left side) | 16:9 |
videos/kidvideo.mp4 | Kid PIN login (fullscreen bg) | 16:9 |
Sidebar & Nav
Top Navigation
White background with glass blur, teal glow line on bottom. Contains: logo + tagline, nav links (Home, Safety/Parents, Pricing), Sign In button, Kid Pin button, hamburger for mobile.
Nav text: "Spark your creativity" (not "Jorrii Spark")
Left Sidebar
Blue-to-purple gradient (#4A8FE7 โ #C27DEB) with teal glow line on right edge. Dark teal text (#0D3B4A). Contains tool links grouped into Create / Build / Learn / Library sections.
Sidebar Links
| Section | Links |
|---|---|
| Create | Make a Picture, Make a Video, Make Music, Make Sounds |
| Build | Spark Studio, ๐ Book Maker, ๐๏ธ Movie Maker, Spark Lab |
| Learn | Spark Missions |
| Library | My Creations, Showcase |
Present on: index.html, kid-dashboard.html, all create tool pages, book-maker.html, movie-maker.html, my-creations.html, showcase.html, spark-lab.html, spark-missions.html
Absent on: parent-login.html, kid-pin.html (immersive layouts)
Responsive Breakpoints
| Breakpoint | Behavior |
|---|---|
900px | Dashboard grid โ single column |
768px | Sidebar hidden, hamburger menu appears, content full-width |
600px | Tool cards: 5 โ 3 โ 2 columns |
480px | Compact spacing, smaller fonts |
Auth Flows
Parent Google Sign-In
- Parent clicks "Continue with Google" on
parent-login.html - Redirects to Google consent screen
- Google sends back to
https://cwudeohugaraangftkfz.supabase.co/auth/v1/callback - Supabase exchanges code and redirects to
https://jorrii.io/parent-login.html - Page detects session โ redirects to
parent-dashboard.html
Parent Email Sign-In
- Parent clicks "Continue with Email"
- Enters email + password
- Calls
sb.auth.signInWithPassword() - On success โ redirect to dashboard
Kid PIN Login
- Kid visits
kid-pin.html - Taps 4-digit PIN on arcade numpad
- Queries
kidstable:WHERE pin = ? - Match โ confetti + welcome screen โ
sessionStorageโ redirect to homepage - No match โ shake animation + "try again"
Kid PIN System
How It Works
- Parents create kid profiles from the dashboard
- Each kid gets a randomly generated 4-digit PIN
- Kids choose an avatar: ๐ฆ ๐ฑ ๐ฆ ๐ธ ๐
- PINs are stored in the
kidstable - Kid login queries by PIN โ no password, no email
- Kid session stored in
sessionStorageas JSON:{id, name, avatar, parent_id}
PIN Collision Risk
With 4-digit PINs (10,000 possible values), collisions become likely around 100+ kids. Future improvement: scope PINs per parent account, or increase to 5-6 digits.
Pricing Plans
| Tier | Price | Yearly | Kids | Img/day | Vid/day | Voice/day | Music/day | Saves |
|---|---|---|---|---|---|---|---|---|
| โจ Spark | Free | โ | 1 | 4 | 0 | 3 | 0 | 10 |
| ๐ Glow | $7.99 | $5.59 | 2 | 15 | 2 | 10 | 2 | 50 |
| ๐ฅ Blaze | $12.99 | $9.09 | 3 | 40 | 5 | 25 | 5 | 200 |
| ๐ Supernova | $29.99 | $20.99 | 5 | 80 | 15 | 50 | 15 | 500 |
| ๐ Infinite | $99 | $69.30 | โ | 100 | 50 | 100 | 50 | โ |
30% yearly discount on all paid plans. Model access increases with tier (free = Nano Banana only, top tiers = all models).
Model Access by Tier
| Tier | Image Models | Video Models |
|---|---|---|
| Spark | Nano Banana only | None |
| Glow | + Imagen Fast, GPT Mini | Wan |
| Blaze | + GPT Image, Imagen Ultra | + Veo 3 |
| Supernova | All models | All models |
| Infinite | All models | All models |
Usage Tracking
Current State
Usage tracking is live. The check_usage() and increment_usage() Supabase functions enforce daily limits per plan. All create pages call these before and after generation. The kid dashboard and tool pages display remaining counts.
How It Works
- Each generation calls
check_usage(parent_id, type)โ returns{allowed, remaining, limit} - If
allowed = false, generation is blocked with friendly message - On success,
increment_usage(parent_id, type)bumps the daily count - Counters reset at midnight UTC (via
usage_tracking.datecolumn) - Limits defined in
plan_limitsview based on subscription plan - Kid dashboard shows usage bars: color-coded by fill percentage
- Nav bar shows remaining counts for quick reference
AI Models
Image Generation
| Model Key | Provider | Min Tier | Notes |
|---|---|---|---|
gpt-image-1 | OpenAI | Spark | Best quality, 4 tokens per generation |
gpt-image-mini | OpenAI | Spark | Fast creative results, 1 token |
imagen-3 | Glow | High quality generation | |
flux-1 | Black Forest Labs | Glow | Fast artistic generation |
recraft-v3 | Recraft | Blaze | Design-focused, sharp outputs |
ideogram-v2 | Ideogram | Blaze | Great with text in images |
Video Generation
| Model Key | Provider | Min Tier | Notes |
|---|---|---|---|
veo-2 | Glow | Great quality and motion | |
veo-3 | Blaze | Cinematic quality with audio | |
kling-1.6 | Kling AI | Glow | Fast, smooth motion |
kling-2.0 | Kling AI | Blaze | High quality, precise camera |
minimax-video | MiniMax/Hailuo | Supernova | Creative and expressive |
runway-gen3 | Runway | Supernova | Industry standard |
Audio Generation
| Model Key | Provider | Type | Tab |
|---|---|---|---|
elevenlabs-v2 | ElevenLabs | Text-to-speech | Voice |
elevenlabs-v3 | ElevenLabs | Text-to-speech | Voice |
openai-tts | OpenAI | Text-to-speech | Voice |
google-tts | Text-to-speech | Voice | |
elevenlabs-sfx | ElevenLabs | Sound effects | SFX |
audiogen | AudioGen | Sound effects | SFX |
stable-audio | Stability AI | Sound effects | SFX |
suno | Suno | Music generation | Music |
udio | Udio | Music generation | Music |
musicgen | Meta | Music generation | Music |
stable-audio-music | Stability AI | Music generation | Music |
๐ Completion Sound Effects
Overview
Every generation page plays a sound effect when creation completes or fails. Sound files are hosted in a sounds/ folder on Hostinger. Uses simple new Audio('sounds/file.mp3').play() wrapped in try/catch.
| Page | Success Sound | Error Sound |
|---|---|---|
| Make a Picture | sounds/picturedone.mp3 | sounds/error.mp3 |
| Make a Video | sounds/videodone.mp3 | sounds/error.mp3 |
| Make Sounds (voice/sfx) | sounds/voicesfxdone.mp3 | sounds/error.mp3 |
| Make Sounds (music) | sounds/musicdone.mp3 | sounds/error.mp3 |
| Book Maker | sounds/bookdone.mp3 | โ |
| Movie Maker | sounds/moviedone.mp3 | sounds/error.mp3 |
| Spark Studio | sounds/picturedone.mp3 | sounds/error.mp3 |
How to Generate Sounds
Use ElevenLabs Sound Effects to generate each file. Keep them 2-3 seconds long. Upload to /sounds/ directory on Hostinger. Files are loaded on-demand (no preloading).
๐ค Character Builder
Overview
Visual character description builder that lets kids see themselves in their creations. Uses physical feature descriptions (skin tone, hair style/color) instead of race/ethnicity labels โ this works with AI image generators without triggering safety filters. Appears in three places: Make a Picture (toggle panel), Spark Lab (collapsible section), and Book Maker (Step 1 wizard replacement).
| Category | Options |
|---|---|
| Person | Girl, Boy, Woman, Man, Baby, Child (+ Cat, Dog, Dragon, Robot in Book Maker) |
| Age | Toddler, Kid (6-10), Tween, Teen, Young adult, Adult, Elderly |
| Skin Tone | 7 color swatches: #FDEBD0, #F5CBA7, #D4A574, #C68642, #A0522D, #6B3A2A, #3B2219 |
| Hair Style | Short, Long, Curly, Afro, Braids, Locs, Ponytail, Twists, Bun, Mohawk, Pigtails, Bald |
| Hair Color | Black, Brown, Blonde, Red, Gray, White, Purple, Blue, Pink |
| Build | Slim, Average, Athletic, Curvy, Stocky, Tall, Short (Make a Picture + Spark Lab only) |
| Personality | Brave, Shy, Silly, Smart, Kind, Curious, Magical, Adventurous (Book Maker only) |
| Extras | Glasses, Freckles, Beard, Mustache, Dimples, Scar, Braces, Tattoos, Headband, Cape, Crown, Wings |
Implementation per Page
- Make a Picture: Toggle panel below prompt. Builds description and appends to prompt text.
- Spark Lab: Collapsible panel with โผ arrow. "โ Add to Prompt" button inserts description.
- Book Maker: Replaces Step 1 choice cards entirely. Live preview + custom text fallback. Sets
choices.characterdirectly.
๐งช Spark Lab
Overview
Advanced prompt building workspace. Category-based suggestion chips for images, videos, voice, SFX, and music. Character Builder panel. Random prompt dice. "Send to" buttons route completed prompts to any generation tool.
| Feature | Details |
|---|---|
| Suggestion Categories | Images: Subject, Setting, Style, Mood. Videos: Scene, Motion, Atmosphere. Voice: Lines, Emotions. SFX: Action, Nature, Fun. Music: Genre, Instruments, Mood. |
| Character Builder | Collapsible ๐ค panel with person/age/skin/hair/color/build/extras. Live preview. "โ Add to Prompt" button. |
| Random Prompts | ๐ฒ Random Prompt (category-appropriate) and โจ Surprise Me (fully random) |
| Send To | Routes prompt text to Make a Picture, Make a Video, Make Music, Make Voices, Book Maker via sessionStorage |
โก Spark Studio
Overview
Visual node-based creative pipeline. Kids connect nodes (text prompts, image generators, video generators, voice/SFX, file uploads) with wires and run the pipeline. Executes in topological order, passing outputs through connections.
| Feature | Details |
|---|---|
| Node Types | Text Prompt, Generate Image (5 models), Generate Video (2 models), Generate Voice (4 presets), Generate SFX, Upload File, Preview |
| Execution | Topological sort of connected nodes โ sequential API calls โ poll jobs โ pass outputs through wires |
| Model Maps | Image: Quick Sketchโflux-schnell, Speed Paintโnano-banana, Color Burstโsd35, Super Artโgenerate-image, Ultra Dreamโrecraft. Video: Dream Motionโtext-to-video, Mega Movieโkling-video |
| File Upload | Reads file as base64 via FileReader, stores in fileInput._base64, passes to connected nodes |
| Completion sound | sounds/picturedone.mp3 on success, sounds/error.mp3 on failure |
๐ Book Maker
Overview
8-page illustrated storybook generator. Kids build a character with the Character Builder (person, age, skin tone, hair, personality, extras) or type a custom description, then pick setting, adventure type, ending, and art style โ GPT-4o writes the story โ images are generated for each page โ interactive book viewer with PDF export โ Save to My Creations gallery.
User Flow
Wizard Steps
| Step | Input | Options |
|---|---|---|
| 1. Character | Character Builder OR custom text | Builder: Person (Girl/Boy/Woman/Man/Baby/Cat/Dog/Dragon/Robot), Age (ToddlerโElderly), Skin Tone (7 swatches), Hair Style (11 types), Hair Color (8 colors), Personality (Brave/Shy/Silly/Smart/Kind/Curious/Magical/Adventurous), Extras (Glasses/Freckles/Cape/Crown/Wings/Scar/Braces/Headband). Live preview builds description. Or type custom. |
| 2. Setting | Preset cards | Enchanted Forest, Outer Space, Underwater Kingdom, Candy Land, Dinosaur Island, Magical Castle |
| 3. Adventure | Preset cards | Rescue mission, Treasure hunt, Making friends, Solving a mystery, Learning a lesson, Big competition |
| 4. Ending | Preset cards | Happy celebration, Funny surprise, Heartwarming lesson, Cliffhanger, Magical transformation |
| 5. Art Style | Preset cards | Pixar 3D, Watercolor, Storybook illustration, Comic book, Japanese anime, Claymation |
Backend: doGenerateStory()
| Detail | Value |
|---|---|
| Lambda route | POST /api/generate-story |
| AI Model | GPT-4o (gpt-4o) |
| Response format | JSON: {title, characterDescription, pages: [{text, imagePrompt}]} |
| Text rules | 1-2 sentences per page, max 25 words, age 6-8 reading level |
| Image prompts | Start with consistent character description for visual continuity |
| Escaping note | Uses string concatenation (not template literals) to avoid Lambda escaping issues |
Tier Gating
| Plan | Books/Month |
|---|---|
| Spark / Glow / Blaze | โ Not available |
| Supernova | 5 books |
| Infinite | 10 books |
Key Files
| File | Purpose |
|---|---|
book-maker.html | Frontend โ character builder, wizard, viewer, PDF export, save to gallery |
index.mjs (Lambda) | Backend โ doGenerateStory(), doSaveBook(), /api/generate-story + /api/save-book routes |
๐๏ธ Movie Maker
Overview
Storyboard-style video editor. Kids drag and drop clips onto a timeline, add images as still clips, insert title cards, pick from 4 transitions, add sound effects at specific timestamps, pick background music, then export as a single video. Exported movies auto-save to gallery via /api/save-movie. Zero server cost for editing โ all processing happens in the browser via Canvas API + MediaRecorder.
User Flow
Clip Sources
| Source | How | Details |
|---|---|---|
| ๐ฌ My Videos | Gallery API | Fetches video items from /api/gallery with auth. Shows thumbnail grid. |
| ๐ผ๏ธ My Images | Gallery API | Fetches image items from gallery. Set duration (2-5s). Renders as full-frame still during export. |
| ๐ Upload | File input | MP4, WebM, MOV. Max 50MB. Creates blob URL. |
| ๐ฌ Title Card | Built-in creator | Custom text + 8 gradient/solid backgrounds. Duration: 2-5 seconds. |
Features
| Feature | Implementation |
|---|---|
| Drag & drop reorder | HTML5 Drag API on clip cards |
| Transitions (4 types) | Click indicator โ popup menu: โ๏ธ Cut, ๐ Fade, โฌ ๏ธ Slide Left, โก๏ธ Slide Right |
| Background music | From gallery (audio items) or file upload. Mixed via Web Audio API. |
| Sound effects track | Add SFX from gallery or upload. Set timestamp for each. Rendered as setTimeout() during export. |
| Image clips | Gallery images rendered via drawImage() with cover-fit for clip duration |
| Preview | Sequential clip playback in built-in video player. Title/image clips rendered to canvas overlay. |
| Export | canvas.captureStream(30) โ MediaRecorder (VP9) โ download as .webm |
| Auto-save to gallery | After export, base64 video sent to /api/save-movie โ S3 + DynamoDB |
| Completion sound | sounds/moviedone.mp3 plays on successful export |
Technical Architecture
Mostly Client-Side
- Rendering: Canvas 2D draws video frames, image stills, and title cards at 1280ร720
- Recording:
canvas.captureStream(30fps)feedsMediaRecorder - Audio mixing: Web Audio API
createMediaElementSource()โcreateMediaStreamDestination() - Sound effects: Scheduled via
setTimeout()at per-clip timestamps during export - Image clips:
drawImage()with cover-fit cropping, held for clip duration - Output: WebM (VP9) at 4Mbps, downloaded as
{title} - Jorrii Spark.webm - Gallery save: After export, base64 sent to
/api/save-movieโ S3 + DynamoDB - Editing cost: $0 โ all client-side. Only save-movie uses Lambda/S3.
Tier Gating
| Plan | Access |
|---|---|
| Spark (free) | โ Not available |
| Glow and above | โ Full access (no API cost since it's browser-based) |
Hosting
Hostinger Setup
- Static file hosting โ upload HTML/CSS/JS directly
- Domain:
jorrii.io - SSL: Enabled (required for Supabase OAuth)
- All files go in root directory
- Images in
images/folder - Videos in
videos/folder
Deployment
How to Update
- Delete old file from Hostinger
- Upload new file
- Hard refresh browser:
Ctrl + Shift + R - If CSS not updating, bump the version:
spark-styles.css?v=4
Cache Busting
Browser caches files aggressively. Always bump the ?v=N parameter on spark-styles.css after making CSS changes. Current version: ?v=2
Troubleshooting
Common Issues
CSS not updating after upload
Fix: Bump ?v=N on the CSS link in HTML, or Ctrl+Shift+R to hard refresh.
Google OAuth redirect loop (RESOLVED)
Status: Fixed. Root cause was PKCE code exchange failure. Fixed by using flowType: 'pkce' in Supabase client config and ensuring correct redirect URIs.
Images show different sizes despite same canvas
Fix: CSS now uses percentage-based sizing (width: 80%) with object-fit: contain. Ensure artwork fills 90%+ of the PNG canvas in Photoshop.
Lambda template literal escaping (RESOLVED)
Issue: Patch script using cat << 'FUNC' in CloudShell mangled backtick template literals inside the doGenerateStory() function, causing SyntaxError: Invalid or unexpected token at deployment.
Fix: Rebuilt function using string concatenation ('string ' + 'string') instead of template literals. Deployed by pasting complete index.mjs directly in Lambda console editor.
Lesson: Never use backtick template literals in Lambda code deployed via shell heredocs. Use string concatenation or deploy via .zip upload instead.
PNGs show black background
Fix: Re-export from Photoshop as PNG with transparency checkbox enabled. Verify checkerboard pattern is visible behind artwork before saving.
Changelog
jorrii.io/game-assets/ (Zara, Nova, Lyra, Blaze, Finn, Koa, Sparky). Step 3 (World) replaced text input with 7 world background thumbnail cards (Candy Kingdom, Outer Space, Jungle, Floating Islands, Underwater City, Haunted Forest, Volcanic Island). Asset library created: 25+ game assets uploaded to jorrii.io/game-assets/ including heroes, enemies (ghost, monster, red robot, bomb), collectibles (coin, star, jewel, heart, treasure), backgrounds, platform, door, shield. Lambda prompt updated: GPT now loads real images via new Image() + crossOrigin, draws background as scrolling tiled pattern, camera follows hero via ctx.translate(-cameraX, 0), HUD drawn after ctx.restore(). R/r/KeyR restart check added. CORS fixed on both API gateways (xm35vp0qoh and ymf072zyfd) via update-api --cors-configuration AllowOrigins=*. Keyboard forwarding: parent page intercepts all keydown/keyup, dispatches to both contentWindow and contentWindow.document, syncs keys object every 50ms via interval, explicit R key handler. save-game route deployed to jorrii-api + registered on xm35vp0qoh.
code_quest_progress table. 7 lessons: (1) Variables/print โ name your hero, (2) If/else โ boss battle, (3) Loops โ score multiplier, (4) Functions โ AI tools unlock ๐ค, (5) AI Images โ links to Make a Picture, (6) AI Sounds โ links to Make Sounds, (7) Ship It โ fill game config โ "Build My Game!" โ make-a-game.html. Supabase table created: code_quest_progress (user_id, lesson_id, completed, xp, completed_at, unique constraint). Spark Game Studio feature set 100% complete.
POST /api/get-game-code, publish/unpublish toggle, delete, empty state. Works for both parent and kid sessions. games-showcase.html: Public community gallery โ hero section with live stats (total games published, unique creators), featured game spotlight card with creator avatar, search bar, game type filter chips, grid of all published games, play modal. No login required to browse. Calls GET /api/get-showcase-games. 3 new Lambda routes deployed on jorrii-api (xm35vp0qoh): GET /api/get-games (user's saved games), POST /api/get-game-code (fetch game HTML from S3), GET /api/get-showcase-games (all published games via GSI). Nav updated: Games Showcase added to sidebar + mobile menu on all pages. Code Quest rename (was Game Curriculum) applied site-wide under Learn section. Spark Game Studio feature set now complete โ only game-curriculum.html (Python lessons) remains for a future session.
make-a-game.html): track selector with Python Curriculum card (lesson preview, AI unlock at lesson 4) and Quick Build card. Game type grid (Platformer, Catch, Quiz, Maze). How It Works 4-step flow. Quick Build page (game-quickbuild.html): 4-step wizard (game type โ hero โ world โ review/generate) with suggestion chips on every field, animated step indicator, 45s generating overlay with live status steps, game rendered in sandboxed iframe, Save + Publish buttons. Lambda route POST /api/generate-game added to jorrii-api (xm35vp0qoh). Uses GPT-4o with 4 tailored prompts per game type. Returns raw HTML5 canvas game string saved to S3 via saveJob. Fixes applied: checkJob now reads jobId from both body and query string params (event.queryStringParameters); frontend polls via POST with JSON body; output is plain string not nested object. Sidebar updated on all 14 pages: ๐ฎ Make a Game (Build section, after Movie Maker) and ๐น๏ธ My Games (Library section, after My Creations). Still TODO: my-games.html, games-showcase.html, game-curriculum.html.
lip-sync.html) removed from all sidebar and mobile menus โ page exists but is not linked. Spark Studio (spark-studio.html) removed from nav โ UI-only, API endpoints not connected. Both marked as Disabled in this admin doc.
doReplicateVideo() fires a background Lambda (/api/process-video) and returns jobId instantly. Kling AI removed (no longer on Replicate). New models: Hailuo-02 (Minimax, default), Seedance-1-lite (ByteDance), Google Veo 3 Fast. Frontend model selector updated. All await (async()=>{})() IIFEs replaced with non-awaited fire-and-forget throughout Lambda.
doGenerateImage() self-invoke pattern was missing from Lambda after a CloudShell session reset. Re-added LambdaClient, InvokeCommand, /api/process-image route, and doProcessImage() background worker. Images now generate reliably without 503 errors.
meta/musicgen) no longer exists on Replicate. Switched to versioned endpoint using hash 671ac645.... Removed await from music IIFE so Lambda returns jobId instantly instead of timing out after 29s.
/api/elevenlabs-voice (doesn't exist) โ corrected to /api/voice. ElevenLabs voice_id now supported with OpenAI TTS fallback. All poll functions updated to accept status === 'succeeded' (Lambda returns succeeded, not completed). Fixed nested output parsing: result.output.output โ URL unwrap across image, video, and sound pages.
stable-mar9 with description: "Working: images, video (hailuo/seedance/veo3), music, voice, sfx โ Mar 9 2026". Can roll back to this version if future deployments break things.
STRIPE_SECRET_KEY โ sk_live_.... Updated pricing.html with live publishable key pk_live_.... Webhook whsec_... confirmed live on "Jorrii Spark Checkout" endpoint. Payment system is now fully live.
/api/save-book โ poll until succeeded โ refresh My Books section. Cover image (page 1 illustration) stored in metadata and displayed on book card. loadMyBooks() called automatically after save.
characterDescription field with precise visual details (age, hair, eyes, skin tone, clothing). This description is prepended to every page image prompt so the character looks consistent across all 8 illustrations. Art style also appended to every prompt. Lambda doGenerateStory() system prompt updated to include character bible in JSON response.
/api/generate-image now creates a job, fires a background Lambda invocation (InvocationType: Event) to /api/process-image, and immediately returns jobId. Background worker runs up to 15 min without timeout. IAM policy lambda-self-invoke added to jorrii-spark-lambda-role. LambdaClient + InvokeCommand imported from @aws-sdk/client-lambda.
gpt-image-1 API was receiving quality: 'standard' which is not a valid value. Fixed default to quality: 'high'. Valid values are: low, medium, high, auto. Book Maker image requests now use quality: 'medium' for speed.
generatePageImage() was calling non-existent /api/flux-schnell. Switched to /api/generate-image. Fixed output parsing: Lambda returns { output: { output: "url" } } (nested), now correctly unwrapped as data.output?.output || data.output. Poll timeout increased to 60 attempts ร 3s = 3 min per image.
doSaveBook() now saves coverImage in metadata alongside pageCount. Cover image = book.coverImage or fallback to book.pages[0].imageUrl. Enables book card thumbnails in My Books gallery.
jorrii-spark-api, breaking: family-code lookup, book-maker, showcase, and gallery. Restored by downloading current Lambda zip, re-injecting doFamilyCode() with AWS SDK v3 (ScanCommand, GetItemCommand, PutItemCommand), fixing body is not defined error, and redeploying. All affected routes confirmed working post-restore.
spark-families table. Lambda doFamilyCode() handles: GET (scan by parent_id, auto-generate if missing), VERIFY (lookup by code). IAM policy spark-families-dynamodb added to Lambda role. Working test code: SPARK-DGAG โ parent_id: 807d1132-99f1-48df-b92d-df8609d2b9fd.
sk_live_.... pricing.html updated with pk_live_.... Live webhook "Jorrii Spark Checkout" confirmed active. Payments are now live.
/api/generate-image fires background worker via InvokeCommand (InvocationType: Event) to /api/process-image, returns jobId instantly. IAM policy lambda-self-invoke added to Lambda role. Images now generate reliably in background.
gpt-image-1 was receiving invalid quality: 'standard'. Fixed default to quality: 'high'. Book Maker uses quality: 'medium'. Valid values: low, medium, high, auto.
/api/save-book โ poll โ refresh My Books. Cover image (page 1) saved in DynamoDB metadata. Book cards show cover art thumbnail. loadMyBooks() auto-refreshes after save.
doGenerateStory() now returns characterDescription field with precise visual details. Prepended to every page image prompt so character looks the same across all 8 pages. Art style also appended to every prompt.
generatePageImage() was calling non-existent /api/flux-schnell. Switched to /api/generate-image. Fixed nested output parsing: data.output?.output || data.output.
generation_log Supabase table. Removed that query โ dashboard now loads KPIs from subscriptions, kids, and Spark gallery API only.
spark-families table. Working code: SPARK-DGAG. IAM policy spark-families-dynamodb added to Lambda role.
profiles Supabase table with unique family_code per parent (format: SPARK-XXXX). Auto-trigger generates code for new signups. Kid PIN query now scoped to verified parent only (~100M combinations vs 10K before). Added 5-attempt rate limiting with 15-minute lockout (localStorage). Parent dashboard shows Family Code with copy button. kid-pin.html redesigned with two-step flow: code entry โ numpad PIN.
/api/replicate-video Lambda route. Kling 2.1 unchanged. New endpoint accepts {prompt, model, aspect_ratio, start_image}. Lambda polls Replicate until completion before saving to DynamoDB. API Gateway route deployed to ymf072zyfd. All 4 models tested end-to-end.
picturedone.mp3/error.mp3), make-a-video (videodone.mp3/error.mp3), make-sounds voice/sfx (voicesfxdone.mp3), make-sounds music (musicdone.mp3), book-maker (bookdone.mp3), movie-maker (moviedone.mp3), spark-studio (picturedone.mp3). All wrapped in try/catch. Hosted in /sounds/ folder.
max-height:450px to viewport-relative max-height:40vh. Ensures full image/video visible with room for prompt/actions below. Feed card previews reduced from 300pxโ220px.
/api/generate-image for everything, producing images instead of videos/sounds. Fixed: make-a-video now uses /api/text-to-video (Wan 2.1) and /api/kling-video (Kling 2.1) โ removed 6 fake models (veo-2, veo-3, kling-1.6, kling-2.0, minimax-video, runway-gen3) replaced with 2 real ones. make-sounds now uses /api/voice (OpenAI TTS, synchronous), /api/elevenlabs-sfx (ElevenLabs SFX, synchronous), and /api/music (MusicGen, async poll). Fixed sound feed filter to include voice/sfx/elevenlabs-sfx/music types.
check_usage Supabase RPC gates from generation pages (make-a-picture, make-a-video, make-sounds). Spark platform is now fully unlimited โ no tier restrictions on any feature. All loadUsage shows "โจ Unlimited". Kid nav shows โ for all counters. loadModels in make-a-video no longer queries subscriptions table โ all models always available. Book Maker tiers: all plans allowed, infinite plan = 9999 books.
saveToGallery now sets isPublic:'false' on item creation (was missing, blocking GSI showcase queries). Share toggle sends createdAt as Number() for DynamoDB key match. Delete also fixed with Number(). Lambda sanitizeError now includes actual error message in E500 responses for debugging. Added CloudWatch logging to share/showcase handlers.
jorrii-spark-api Lambda with isolated DynamoDB tables (spark-gallery, spark-jobs) and S3 buckets (jorrii-spark-creations, jorrii-spark-jobs-output). API Gateway: ymf072zyfd.execute-api.us-east-2.amazonaws.com. Lambda auto-saves all generations to S3 + DynamoDB (no more Supabase gallery_items). Gallery, share-to-showcase, and delete all routed through Spark API. Kid PIN sessions now take priority over parent Google login across all pages. Fixed GPT Image 1 size validation (1024x1024, 1024x1536, 1536x1024 only). Updated 10 HTML files: make-a-picture, make-a-video, make-sounds, book-maker, movie-maker, my-creations, showcase, kid-dashboard, parent-dashboard, admin.
.tool-card.book CSS with pink border. Movie Maker links also added to all pages.
/api/generate-story confirmed working. Full test returned valid 8-page JSON.
TODO
| Priority | Task | Status |
|---|---|---|
| โ | Fix Google OAuth redirect loop | Done |
| โ | Build pricing.html page | Done |
| โ | Build make-a-picture.html | Done |
| โ | Build make-a-video.html | Done |
| โ | Build make-sounds.html (Voice + SFX + Music) | Done |
| โ | Build my-creations.html (gallery) | Done |
| โ | Build kid-dashboard.html | Done |
| โ | Create usage_tracking table + functions | Done |
| โ | Create gallery storage (DynamoDB spark-gallery + S3) | Done |
| โ | Create subscriptions table | Done |
| โ | Fix kid PIN session key + redirect | Done |
| โ | Purple footer on all pages + Disclosures link | Done |
| โ | Update all sidebar/mobile/footer links | Done |
| โ | Build book-maker.html (8-page storybook wizard) | Done |
| โ | Lambda: /api/generate-story endpoint + doGenerateStory() | Done |
| โ | Build movie-maker.html (storyboard video editor) | Done |
| โ | Add Book Maker + Movie Maker to all page navs | Done |
| โ | Parent login trust section | Done |
| โ | Build spark-studio.html (visual node pipeline) | Done |
| ๐ด High | Build disclosures.html | TODO |
| โ | Kid nav on tool pages (hide pricing, show usage when kid logged in) | Done |
| โ | Movie Maker: save exported movies to gallery | Done |
| โ | Book Maker: save books to gallery with flipbook reader | Done |
| โ | Character Builder on make-a-picture, spark-lab, book-maker | Done |
| โ | Completion sound effects on all generation pages | Done |
| โ | Movie Maker: image clips, SFX track, 4 transitions | Done |
| โ | Build lip-sync.html (4 modes, 7 characters, 3 models) | Done |
| โ | Lambda: /api/generate-lipsync endpoint + doLipSync() | Done |
| โ | API Gateway route: POST /api/generate-lipsync | Done |
| โ | Add ๐ Lip Sync to all page sidebars + mobile menus | Done |
| โ | Fix whiteโyellow Chewy sidebar on movie-maker, my-creations, parent-dashboard | Done |
| โ | Kid dashboard colorful redesign (dark theme, glowing cards, usage bars with limits, filter tabs) | Done |
| โ | Reference image support for Wan 2.1 video (auto i2v switch) | Done |
| โ | Spark Studio real API wiring (was fake timeouts) | Done |
| โ | Detail view sizing fix (40vh viewport-relative) | Done |
| โ | Wire Stripe for paid subscriptions (live mode) | Done |
| ๐ก Medium | Upload sound effect files to /sounds/ folder on Hostinger | TODO |
| โ | Deploy Lambda with save-book + save-movie routes | Done |
| โ | API Gateway routes: POST /api/save-book, POST /api/save-movie | Done |
| ๐ก Medium | Movie Maker: actual transition rendering during export (fade/slide canvas effects) | TODO |
| โ | Public Showcase page (shared gallery via /api/showcase) | Done |
| ๐ก Medium | Content review feature in parent dashboard | TODO |
| ๐ข Low | PIN collision prevention (scope per parent) | TODO |
| ๐ข Low | Separate showcase API for kid-specific content | TODO |
| ๐ข Low | videos/login.mp4 โ create parent landing video | TODO |
| ๐ข Low | videos/kidvideo.mp4 โ create kid PIN video | TODO |
| ๐ด High | Fix Book Maker โ not generating/saving correctly | TODO |
| ๐ก Medium | Register /api/process-video route in API Gateway (self-invoke works but route not formal) | TODO |
| ๐ก Medium | Verify voice page end-to-end with ElevenLabs voice IDs | TODO |
| ๐ข Low | Kid dashboard video background | TODO |
| โ | Book Maker: auto-save books to My Books gallery with cover image | Done |
| โ | Image generation: fix fire-and-forget Lambda self-invoke pattern | Done |
| โ | Book Maker: character description injected into all image prompts for consistency | Done |
| ๐ข Low | Movie Maker: FFmpeg.wasm for MP4 export (currently .webm only) | TODO |
| ๐ก Medium | Upload sound effect files to /sounds/ folder on Hostinger (bookdone, videodone, error etc.) | TODO |
| ๐ก Medium | Connect Spark Studio nodes to real API endpoints | TODO |
| ๐ก Medium | OG image redesign โ include Jorrii Spark logo for social sharing | TODO |
| ๐ด High | Build disclosures.html (legal page) | TODO |