# Template import / export (portable bundles) Move a template — **everything**: container, projects, all scenes + editable fields, shared colours/layers, the categories & tags it belongs to, and the asset files — between environments (e.g. local → live). A **bundle** is a self-contained directory: ``` dist/template-bundles// ├── template.json # every DB row related to the template └── assets/ # the media it references (thumbnails, scene stills, preview…) ``` ## Export (from the source DB) ```bash PYTHONIOENCODING=utf-8 python scripts/export_template.py # → dist/template-bundles// # non-default source DB: PSQL="psql 'postgresql://user:pass@host:5432/flatrender'" \ python scripts/export_template.py ``` ## Import (into ANY target DB) The importer prints idempotent SQL — pipe it to the target's `psql`. It **replaces** any template with the same slug (one cascading delete), recreates rows verbatim (original UUIDs, so foreign keys stay intact), and **merges categories & tags by slug** so they line up with whatever the target already calls them. ```bash # local: python scripts/import_template.py dist/template-bundles/ \ | docker exec -i fr2-postgres psql -U postgres -d flatrender # live: python scripts/import_template.py dist/template-bundles/ \ | psql "postgresql://user:pass@live-host:5432/flatrender" ``` ### Assets The SQL only moves DB rows. Place the bundle's `assets/` into the target's `template-media`: ```bash # copy locally while importing: python scripts/import_template.py --assets-to ./public/template-media | ... # live docker frontend: for f in /assets/*; do docker cp "$f" :/app/public/template-media/; done # live MinIO/object store: mc cp --recursive /assets/ myminio//template-media/ ``` ## Guarantees & notes - **Idempotent** — re-importing the same bundle re-creates the template cleanly. - **Cross-DB safe** — UUIDs are preserved; categories/tags merge by their unique slug. - **Round-trip tested** — DB → bundle → DB restores identical counts and values. - **Not exported** (intentionally): user data — comments, favourites, view/use counts. - **External (http) media** referenced by a template is flagged on export but not bundled — host it on the target yourself. - Scope today covers FlexStory/Remotion + standard fields. AEP-specific child tables (characters, colour presets) are an easy extension — add them to the export query and the importer's insert list (both are data-driven).