The constraint
Image models drift. A headshot, a wardrobe turn, a library interior, and a medium shot of the same figure will not stay one canon unless identity, set, and camera are locked assets — not a prompt you hope the model remembers.
2025 · Generative · Architect, Engineer & Technical Product Lead
Creative velocity without drift — identity, set, and shot locks that hold canon across providers, models, and cuts.
canon-forge ↗Image models drift. A headshot, a wardrobe turn, a library interior, and a medium shot of the same figure will not stay one canon unless identity, set, and camera are locked assets — not a prompt you hope the model remembers.
Built a TypeScript/React/Vite suite (CharacterForge, SetForge, CompositorForge, SceneForge) with an Express proxy. Generations go through /api/generate (Gemini, xAI Grok Imagine, Venice, Bedrock Titan/SD, local SD). Default client provider is xAI. Canon stills attach as reference or init images where the provider allows it. SceneForge builds keyframe sequences and a flipbook; /api/generate-video calls Veo for 8-second clips. Profiles persist in localStorage. GitHub Actions lint and build; node:test covers identityLock and provider helpers.
Treated identity as an approved asset plus a written identity-lock block. The canon headshot is attached when the provider accepts a reference image.
Sets declare spatial invariants, landmarks, forbidden changes, and a lighting-rig lock. Wide/medium stills become the set’s reference the same way the headshot does for a face.
CompositorForge only fires after character, set, action, lens, and landmark lock are specified. The model is a renderer inside a shot list.
Character, Set, Compositor, and Scene tabs share CharacterProfile / SetProfile / CompositeConfig / KeyframeScene so a later frame cannot quietly become a different actor in a different room.
Moved keys server-side. Gemini, xAI, Venice, Bedrock, and local SD share one generate path. Veo is the video path.
A three-state dialog (upload → generate → approve/retry/skip) locks one reference photo per character: image-type and 10MB checks, client-side downscale to 1024px before base64, then that headshot rides as an image part on every later generation. Not a face-embedding or InstantID model — and skippable, characters without a locked face still work.
A free-text Signature Wardrobe field on the character profile gets appended to every generation prompt — character shots, composites, and keyframes — so the model can't invent different clothing between frames. A third lock alongside identity and set, not folded into either.
Indoor/outdoor sets declare spatial invariants, fixed landmarks, forbidden changes, and a lighting-rig lock in the prompt.
Compositor specs encode shot type, camera angle, lens preset, subject distance, emotion, and landmark lock — production language, not a vibes prompt.
Express /api/generate routes Gemini, xAI Grok Imagine, Venice, Amazon Bedrock (Titan / SD), and local Stable Diffusion. Client default in source is xAI. Venice doesn't accept reference images — canon-locked generations fall back to description-only there, disclosed in the UI, not a silent quality drop.
/api/generate-video calls Veo (default veo-3.0-fast-generate-001) for an 8-second 16:9 clip. A separate path from SceneForge — not called by it.
Auto or manual beat descriptions stage a scene into timed frames — all dispatched in parallel on Forge Keyframes, each frame's status updating independently. Playback activates the moment the first frame lands, not after the whole batch; any single frame retries without restarting the sequence. A flipbook to validate scene flow before Google Flow, not an NLE and not a Veo integration.
React 19 + Vite 6 + TypeScript + Express. Keys stay on the server. This portfolio cannot host it.
Face mesh, set wireframe, locked composite, and frame strip on one console — identity through the cut.
Proves: I can design a generative production pipeline that keeps identity, set, and shot canon locked across providers.
Public source at github.com/rubyrayjuntos/canon-forge. Needs provider keys on the Express server. This static portfolio cannot host it. Render.yaml and a GHCR Docker workflow exist; the Dockerfile in tree is a dev stage. Not a multi-tenant SaaS.
Four-forge architecture (Character, Set, Compositor, Scene) with identity-lock prompt contracts, multi-provider routing (Gemini, xAI, Bedrock, Venice, local SD), and Veo video.