- scripts/seed_instagram_promo.py — dedicated seeder for the 5-scene FlexStory IG
promo (the generic seeder only handles CharacterStory's 2-text-per-scene shape).
Scenes keyed `<BlockId>__<n>` (render decodes the block from the key); each scene's
content-elements are that block's real fields (Text + Media); colours as shared.
render_remotion_comp = FlexStory-<asp> so GetFlexStoryProps routes it.
- public/template-media/InstagramPromo* — thumbnails, per-scene stills, preview MP4.
Applied to local fr2-postgres + fr2-frontend: container fr-instagram-promo (3 aspects,
15 scenes, 138 fields), served by the gateway and the /templates detail page (200).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each scene now carries both a still (content.scenes.image) AND a short ~1.5s LOOP
video (content.scenes.demo), so the studio scene cards show a looping preview, not
a static swatch.
- LOOP_SCENES = {CharacterStory, LogoMotion3D}: their scenes get a dedicated
per-scene loop ({tid}-{asp}-c{n}-loop.mp4 / {tid}-{asp}-loop.mp4); other
templates fall back to their full preview MP4.
- Renders 42 loops: LogoMotion3D ×3 (frames 30–74) + CharacterStory 13 scenes ×3
aspects (frames (n-1)*90+20 … +64), each a 45-frame / 1.5s clip mid-scene.
- Seed sets image + snapshot_url + demo per scene; verified all 42 serve 200 and
the DB wires each scene to its own still + loop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scenes were seeded with just a scene_color_svg swatch — content.scenes.image /
snapshot_url were empty, so the studio/admin scene previews showed swatches, not
the actual scene. Now every scene gets a real rendered image:
- single-scene templates → their per-aspect thumbnail;
- multi-scene templates → one still per scene, captured at that scene's own frame.
Adds the 39 CharacterStory per-scene stills (13 scenes × 3 aspects), each rendered
at (sceneIndex*90 + 45). LogoMotion3D's single scene now points at its thumbnail.
Verified: DB image/snapshot_url populated, all per-scene images serve 200, and the
stills are distinct per scene (c7 = «یک مانع», kicker ۰۷/۱۳).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First template built through the new flow (brief → quality-gate approval → build →
seed → deploy). Tech/3D logo motion: a 3D metallic card + radial light rays + lens
flare + bloom (genuine @remotion/three), with the user's uploaded logo composited
on the card as a reliable HTML <Img> (renders any SVG/PNG/data-URI; static camera
keeps it aligned), brand text + tagline, grain. Falls back to a branded play-mark
when no logo is set. Re-flows across 16:9/1:1/9:16.
- LogoMotion3D.tsx registered per aspect in Root.tsx.
- Seeded as fr-logo-motion-3d: text fields (brandText, tagline) + a logoUrl image
upload field + the dark-tech palette (light text) + per-aspect previews.
- 3 thumbnails + 3 preview MP4s rendered, deployed; detail page + assets serve 200.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes the render boundary so a user's scene list (order, per-scene content,
per-scene duration, theme) actually drives the FlexStory engine — the one gap the
scene-engine mapping found.
- render-svc GetFlexStoryProps (db.go): structured per-scene query that groups
saved_scene_contents BY scene (the flat GetRenderBindings union collides when
scenes share keys like "title"), recovers blockId from the scene key
("<BlockId>__<n>"), and emits the FlexStory props object
{scenes:[{blockId,durationSec,props}], accentColor, …}.
- render-svc Claim (internal.go): when the template is Remotion + comp starts with
"FlexStory", send that object as a single "__flexprops__" binding (no protocol
struct change).
- node-agent remotionProps (remotion.go): if "__flexprops__" is present, pass it
to `remotion render --props` verbatim (it's the complete props object).
- scripts/seed_flexstory.py: seeds the CharacterJourney template (7 scenes, theme
colours, FLEXIBLE) with blockId-encoded scene keys, so the studio's existing
CopyTemplateGraphAsync copies them into saved_scenes with zero studio-svc change.
Both Go services compile; template is live in the catalog (detail 200, per-aspect
previews). End-to-end render verification needs a live Remotion render node.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Template detail page now shows the render matching the SELECTED aspect (poster +
preview video) instead of the 16:9 cover cropped into a 9:16/1:1 box. TemplateVariant
carries per-aspect image/previewVideo; fetchTemplateVariants + the detail page wire them.
- AppShowcase3D ships a distinct preview video per aspect (seed PERASPECT_VIDEO).
- Frontend Dockerfile: Alpine -> node:20-slim (glibc). Fixes next-swc ("ld-linux..."
load failure that broke `next build` once libc6-compat was removed) AND the original
CI Alpine-CDN issue. Healthcheck switched to node (slim has no wget).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New @remotion/three template: titanium flagship phone (thin rim, glossy black
glass, rounded-corner screen via ShapeGeometry, dynamic island, side buttons),
light keynote studio (contact shadow + env reflections + DOF + soft bloom),
film grain + entrance light-sweep. All 3 aspects re-flowed.
- Editable screenUrl (user app screenshot textured onto the screen via TextureLoader
+ delayRender), appName/tagline/cta, 4 colours (dark text on light bg).
- Add pick(wide,square,tall) helper to lib/aspect.ts (Tier-0 from the R&D).
- Seed: AppShowcase3D + per-template text colour; built with the flat-artist skill.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Render engine
- Add Remotion (code-based) as a 2nd render engine alongside After Effects.
node-agent dispatches on Job.Engine; RunRemotion maps bindings -> --props,
renders native then ffmpeg-scales to the quality tier (aspect-preserving).
- content.projects.render_engine + render_remotion_comp (migration 32);
render-svc claim resolves engine and routes (skips .aep for Remotion).
- Admin TemplatesAdmin gains an engine picker + Remotion composition id field.
Template pack (services/remotion)
- 16 branded, Persian (Vazirmatn), color- and text-editable templates, each in
3 aspects (16:9 / 1:1 / 9:16): LogoMotion, Opener, InstaPromo, YouTubeIntro,
Slideshow, HappyBirthday, SalePromo, QuoteCard, EventInvite, Countdown,
GlitterReveal (editable logo image), NowruzGreeting (animated characters),
and 4 cinematic 3D templates via @remotion/three (Hero3D, Nowruz3D,
Birthday3D, Promo3D) with reflections + bloom/DOF/vignette.
- scripts/seed_remotion_templates.py seeds containers/projects/scenes/colors.
Pricing
- Rewrite /pricing to the seconds-based model (charge = length x resolution),
data-driven from /v1/plans, Toman, broker checkout.
Coming-soon
- Persian experimental-build overlay on all pages (launch date + countdown).
Fixes
- middleware matcher bypasses all static asset paths; catalog mapping passes
cover image + preview video so real thumbnails render.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The single-file bind mount ./scripts/init-db.sh left a stale empty dir in the
reused act_runner workspace → mounted as a directory → migrations never ran →
empty schemas → backend 28P01/connection failures. Move the init script to
deploy/postgres-initdb/00-init.sh and mount the whole DIR at
/docker-entrypoint-initdb.d (robust, like the migrations dir). Deploy checkout
now 'git clean -ffd' to purge stale workspace dirs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- AepImportService: the global Scene HasQueryFilter(DeletedAt==null) was hiding
soft-deleted rows, so the revive never matched and the importer re-inserted →
scenes_project_id_key violation. Add .IgnoreQueryFilters() to the load. (apply
now revives + returns 200, verified.)
- node-agent: ClearAECrashState() deletes AE's SCRPriorState.json before each
launch so the 'Crash Repair Options' dialog can't hang a headless scan/render.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add full V2 architecture: identity, content, studio (.NET 10) and file,
render, notification, gateway (Go) services with vendored deps, plus DB
migrations, event/API contracts, and an init-db script.
Wire the Next.js frontend to the gateway: server-side JWT auth routes
(login/register/refresh/logout/me), gateway fetch helper, and session/
cookie/jwt helpers under src/lib.
Containerize the stack via docker-compose.v2.yml and per-service
Dockerfiles. Base images resolve through a Nexus mirror (Docker Hub) and
MCR directly; npm/NuGet pull from Nexus groups. Self-host fonts via
next/font/local to avoid Google Fonts (geo-blocked).
Add CI workflow and ignore .env.v2, *.stackdump, and .NET bin/obj.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>