* feat: add Motion Design skill and OD Next task route
* fix(web): rename motion design entry and place it second
* fix(web): reconcile motion design catalog consumers
* feat(web): add motion design templates to Home and Community
Five motion design example templates (3D procedural island, explainer,
product launch, showreel, data story), chosen by community reach, under the
Home motion-design chip and a new Community "Motion design" type.
Each template follows the bundled example layout: an OD-generated
example.html with its runtime libraries under assets/, an HTML preview baked
by the existing preview pipeline, and a SKILL.md that carries example.html
as the reference when the card is picked on the OD Next motion-design route.
Home cards ship curated copy for every UI locale. Motion templates stay off
the Video and HyperFrames chips.
* fix(skills): keep motion-design procedural layers visible in video export
The MP4 exporter seeks timelines with callbacks suppressed
(renderSeek(t, { suppressEvents: true })), so content drawn only from a GSAP
onUpdate callback is missing from exported video. Recommend a per-frame draw
loop that reads the timeline clock, and state that visible content must not
depend on timeline callbacks. The OD Next task asset is re-synced with
scripts/sync-motion-design-skill.ts.
* fix(motion): preserve reference assets and exported animation frames
* feat(skills): integrate curated motion helpers with complete runtime files
* feat(skills): add Huashu, Oil Motion and Motion.Lab adapters
* test: classify animate design guidance in narration guard
* feat(motion): refine five community templates and portable previews
* fix(motion): refine launch transitions and center gallery previews
* fix: allow free-form briefs on automatic motion task route
* feat(motion): add template soundtracks and audio export
* fix(motion): require rendered MP4 alongside editable video source
* test(motion): align strategy activation expectation with package version
* fix: scope motion delivery and make editable sources playable
* fix(motion): bundle source dependencies and valid closing protocol
* feat(motion): rebuild the five templates on the most-viewed community posts
Re-select topics by single-post views in the latest awesome-opus-5.5-video
snapshot and anchor each template to the top eligible post of its genre:
camera-focus explainer, showreel, product launch, procedural island and a
new wordless animated short that replaces the data story.
All five example.html files are hand-authored canvas/Three.js films drawn by
one render(t) from the GSAP master timeline, so preview, scrubbing and MP4
export produce identical frames. Each ships an original procedural
soundtrack, updated SKILL.md and 19-locale copy; Home order follows reach.
* fix(plugins): load bundled fonts in plugin previews
Plugin previews blocked every bundled font: the preview CSP had no font-src,
and relative url() references inside inline <style> blocks kept pointing at
the preview URL instead of the plugin folder. Allow same-origin fonts, map
inline-style url() references through the existing asset route (escapes,
absolute and data: URLs stay untouched), and serve font files with font
MIME types.
* feat(community): make motion template Use match the Home example pick
Community 「做同款」 on a motion design template now binds it as that type's
own example card, carrying the type's project metadata, so the run takes the
same OD Next motion-design route as a pick from Home's motion design list and
delivers the MP4 together with the editable source. Other task types keep
the existing plugin-pinning hand-off.
Community use clicks now record use_source (card | detail_modal) and
use_action (use | use_with_query); the details modal Use is tracked for the
first time. The Home hand-off no longer records a second community_gallery
click for uses Community already tracked.
* fix(plugins): count the five motion templates in the official registry metadata
* fix(media): keep HyperFrames audio filters compatible with FFmpeg 4.1
CI's bundled Linux FFmpeg 4.1 rejects adelay all=1 and amix normalize=0.
Make each track stereo and delay both channels explicitly, skip amix for a
single track, and undo amix averaging with a gain for several tracks.
* fix(motion): keep template previews bakeable on slow CI renderers
CI's software-GL baker skipped the 3D island (preview readiness timeout):
under slow frames GSAP lag smoothing slowed the timeline, so the 8 s
poster frame never arrived within the baker's 15 s wait. Play every
template on the wall clock and move the island poster to 6 s. With
simulated 300 ms frames all five now report ready within 10 s.
* feat(motion): add the kinetic typography template
Template selection now follows the motion design spec's four content types
(brand and product films, kinetic typography, explainer animation, procedural
art). Kinetic typography takes the fifth slot, replacing the animated short.
The new template is a 15-second, 120 BPM type film with an original
soundtrack and 19-locale copy.
* fix(motion): let the project motion player fit template stages
Inside a project the motion source player wraps the composition, fits it and
adds its own controls. The templates also scaled their stage, so editable
sources from Remix and Community use rendered at a fraction of the preview.
Templates now keep their own fit and controls only outside that player.
* feat(motion): restage the 3D island as a midday lagoon
The island moves from golden hour to a bright tropical midday closer to its
anchor post: a shader lagoon coloured by a baked depth map with ripples,
shallow-water shimmer and shore foam, a wide white-sand beach, palms and
instanced bushes, a village with a pier, soft sun shadows and a lower
camera path. The CPU wave mesh is gone, so frames cost no more than before.
Copy is updated in all 19 locales.
* fix(motion): keep each soundtrack inside the composition root
A Community use regenerated the island source tail and dropped the root
<audio> element, so its MP4 had no sound. Templates now place the element
inside the composition root next to the stage.
* docs(motion): state the template selection rule as complete works
* fix(motion): enforce video clocks and bound content verification
* feat(motion): replace the motion templates with remakes of viral posts
The five Motion design templates are now frame-faithful remakes of viral
motion posts, so each preview shows the look users came for: the 15-second
motion designer showreel, a high-energy motion reel (copy set in English), a
one-shape UI motion piece, a pixel-art wizard and a 20-second electric-blue
tech reel. Each ships open-licensed fonts, an original soundtrack, the
creator's published prompt where one exists, and credits its source post.
The explainer, product launch, 3D island and kinetic type templates are
removed. Tests follow the new set; a backward-seek check now covers hidden
WebGL layers.
* feat(motion): feature The Future Is Already Here first and start preview sound with the film
* chore: ensure PR CI
* fix(motion): match The Future Is Already Here controls and reorder the motion templates
* fix(motion): make the one-shape UI preview controls legible
* fix(motion): hide The Future Is Already Here controls inside the project player
* fix(motion): plan suitable sound and synchronize source audio playback
* feat(motion): keep remake soundtracks by default and fade exported audio where it stops
* test(motion): cover audible source controls in Chromium
* fix(test): use explicit ESM imports in audio player regression
* fix(motion): align preview track discovery with video export
* feat(motion): autoplay looping HTML without a player bar
* fix(test): consume the built motion playback contract
* docs(motion): state explicit soundtrack rules for make-same and the music line in replies
* chore(motion): version the audible looping delivery profile
* docs(motion): let template sound rules lead the general policy and freeze the audio contract
* fix(motion): scope autoplay to declared video motion sources
* fix(motion): reject audible MP4s under an explicit silent contract
* docs(motion): drop the routine music note from make-same replies
* test(motion): align delivery regressions with looping source playback
* fix(motion): isolate preview and audio export from legacy HyperFrames
* test(motion): retain the existing desktop legacy audio limitation
* fix(motion): suspend audio when previews leave the active workspace
* feat(motion): replace two motion templates with a product promo and a visual lesson; sign the showreel as Open Design
* feat(motion): give the showreel the Open Design palette and a full-size stacked wordmark
* feat(motion): give the product promo a livelier mascot girl
* refactor(motion): rebuild The Future Is Already Here as readable, editable scene code
* fix(motion): pick gallery cover frames that survive the baker's capture delay
* feat(motion): sharpen the showreel opener, depth, truchet and end card
* feat(motion): make the product promo mascot talk, add a speaking score and the flow pop
* feat(motion): give the visual lesson the original's paper-collage texture
* fix(motion): bundle gallery covers for fresh branch checkouts
* feat(motion): feature and refine Bring Ideas to Life
Adapt the paper story around OpenDesign capabilities, with short rounded hands, clearer timing, continuous paper actions, and a larger audience invitation. Feature it first in Motion and synchronize localized names, metadata, cover, guidance, and regressions.
Keep product promo audio music-only with sparse percussion.
* fix(motion): stabilize artifact cards and capture declared covers
* fix(web): share creation type order with community
* test(motion): exercise audio controls through project UI lifecycle
* fix(motion): scope live cover behavior to actual video sources
* test(motion): use real HEAD responses in cover regressions
---------
Co-authored-by: bone3deep1962-collab <bone3deep1962@gmail.com>
Co-authored-by: William <zhouhaoran@refly.ai>
Co-authored-by: open-design-crew[bot] <4197780+open-design-crew[bot]@users.noreply.github.com>
Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
Co-authored-by: Amy <1184569493@qq.com>
19 KiB
Quickstart
English · Português (Brasil) · Deutsch · Français · 日本語 · 한국어 · 简体中文 · 繁體中文 · ภาษาไทย
Run the full product locally.
Environment requirements
- Node.js:
~24(Node 24.x). The repo enforces this throughpackage.json#engines. - pnpm:
10.33.x. The repo pinspnpm@10.33.2throughpackageManager; use Corepack so the pinned version is selected automatically. - OS: macOS, Linux, and WSL2 are the primary paths. If your agent CLIs run inside WSL2, use the
WSL2 setup guide. Windows native is supported; seedocs/windows-troubleshooting.mdfor common PowerShell setup gotchas. - Optional local agent CLI: OpenDesign supports a registry of local runtimes, including Claude Code, Codex, Devin for Terminal, OpenCode, Cursor Agent, Qwen, Qoder CLI, GitHub Copilot CLI, and others. The current list lives in
apps/daemon/src/runtimes/registry.ts. If none are installed, use a BYOK runtime configured in Settings.
Local agent CLI and PATH
The daemon scans your PATH (plus common user toolchain directories). If you install a CLI with npm install -g or Homebrew and OpenDesign still shows it as not installed, the GUI may be starting with a minimal PATH that does not include your global npm or Homebrew bin directory (common on macOS when the app is not launched from a full login shell). Ensure the executable’s directory is on PATH for the process that runs the daemon, then use Rescan in Models & providers → Local CLI.
nvm / fnm are optional convenience tools, not required project setup. If you use one, install/select Node 24 before running pnpm:
# nvm
nvm install 24
nvm use 24
# fnm
fnm install 24
fnm use 24
Then enable Corepack and let the repo select pnpm:
corepack enable
corepack pnpm --version # should print 10.33.2
Docker Setup
Run OpenDesign in a fully containerised environment without installing Node.js or pnpm locally.
Requirements
- Docker Desktop
- Docker Compose v2
Verify Docker is installed correctly:
docker compose version
Start OpenDesign
From the repository root:
-
Change to the deploy directory and copy the environment template:
cd deploy cp .env.example .env -
Generate a secure token:
openssl rand -hex 32 -
Open
.envin your editor, findOD_API_TOKEN=, and paste the generated token there.
Then start the service:
docker compose up -d
Open the app in your browser:
http://127.0.0.1:7456
The first startup may take a few seconds while Docker pulls the latest image.
Common Docker Commands
View logs
docker compose logs -f
Restart containers
docker compose restart
Stop containers
docker compose down
Pull the latest image
docker compose pull
docker compose up -d
Remove all local app data
docker compose down -v
Environment Configuration
Create a deploy/.env file to override the default configuration. Start from the provided example:
cp deploy/.env.example deploy/.env
Edit deploy/.env to set your own token and adjust other values as needed:
# Port exposed on the host
OPEN_DESIGN_PORT=7456
# Container memory limit
OPEN_DESIGN_MEM_LIMIT=384m
# Allowed CORS origins
OPEN_DESIGN_ALLOWED_ORIGINS=https://yourdomain.com
# Docker image tag
OPEN_DESIGN_IMAGE=ghcr.io/nexu-io/od:latest
# Required API token for daemon security
# Generate one with: openssl rand -hex 32
OD_API_TOKEN=
Persistent Storage
Before documenting, changing, or choosing any persistent daemon storage path,
you MUST read the root AGENTS.md section Daemon data directory contract.
This Quickstart MUST NOT restate that contract or define storage paths.
Notes
- Docker mode is ideal for contributors who do not want a local Node.js or pnpm setup.
- The container exposes the production daemon build directly on port
7456. - For development workflows and advanced local setup, see the rest of this Quickstart guide.
One-shot (dev mode)
corepack enable
pnpm install
pnpm tools-dev run web # starts daemon + web in the foreground
# open the web URL printed by tools-dev
For the desktop shell and all managed sidecars in the background:
pnpm tools-dev # starts daemon + web + desktop in the background
On first load, the app detects the available local runtimes and also offers BYOK runtimes configured in Settings. Choose a runtime, a design template, and a design system, then type a prompt and hit Send. Structured local runtimes write canonical project files and stream file/tool events; the file workspace and preview update from those writes. Plain text-only and BYOK runs instead return a complete <artifact> block for the host to parse. Before documenting or changing any artifact storage path, you MUST read AGENTS.md → Daemon data directory contract.
The Design systems catalog is loaded from the DESIGN.md packages in design-systems/. Pick one to apply that brand's visual language to the artifact.
The Templates catalog comes from design-templates/ and groups artifact formats for prototypes, decks, documents, images, video, and audio. skills/ is reserved for functional capabilities that the agent invokes while it works. Pair a template with a design system to produce an artifact in the chosen visual language.
Other scripts
pnpm tools-dev # daemon + web + desktop in the background
pnpm tools-dev start web # daemon + web in the background
pnpm tools-dev run web # daemon + web in the foreground (e2e/dev server)
pnpm tools-dev restart # restart daemon + web + desktop
pnpm tools-dev restart --daemon-port 7457 --web-port 5175
pnpm tools-dev status # inspect managed runtimes
pnpm tools-dev logs # show daemon/web/desktop logs
pnpm tools-dev check # status + recent logs + common diagnostics
pnpm tools-dev stop # stop managed runtimes
pnpm --filter @open-design/daemon build # build apps/daemon/dist/cli.js for `od`
pnpm --filter @open-design/web build # build the web package when needed
pnpm typecheck # workspace typecheck
pnpm tools-dev is the only local lifecycle entry point. Do not use the removed legacy root aliases (pnpm dev, pnpm dev:all, pnpm daemon, pnpm preview, pnpm start).
tools-dev automatically loads workspace env files before resolving ports, namespaces, and child process environments. Default precedence is .env.development.local, then .env.local, then .env.development, then .env; env files override ambient shell exports so project-local config wins. Use --no-env-file to disable loading or repeat --env-file <path> to use explicit env files instead.
The development daemon defaults to the workspace-pinned Vela CLI installed by pnpm install, including its matching OpenCode companion. This prevents an older global vela from accepting sign-in but failing workspace billing or task launch. An explicit VELA_BIN or Settings → CLI env selection still takes precedence. Startup prints the selected workspace binary; if the optional package is absent it warns before falling back to PATH.
During local development, tools-dev starts the daemon first, passes its port into apps/web, and apps/web/next.config.ts rewrites /api/*, /artifacts/*, and /frames/* to that daemon port so the App Router app can talk to the sibling Express process without CORS setup.
Media generation / agent dispatcher checks
Image, video, audio, and HyperFrames skills call the local od CLI through environment variables injected by the daemon when it spawns an agent:
OD_BIN— absolute path toapps/daemon/dist/cli.js.OD_DAEMON_URL— the running daemon URL.OD_PROJECT_ID— the active project id.OD_PROJECT_DIR— the active project's file directory.
If media generation fails with OD_BIN: parameter not set, apps/daemon/dist/cli.js missing, or failed to reach daemon at http://127.0.0.1:0, rebuild the daemon CLI and restart the managed runtime:
pnpm --filter @open-design/daemon build
pnpm tools-dev restart --daemon-port 7457 --web-port 5175
ls -la apps/daemon/dist/cli.js
curl -s http://127.0.0.1:7457/api/health
Then open the project from the OpenDesign app again instead of resuming an old terminal agent session. A daemon-spawned agent should see values like:
echo "OD_BIN=$OD_BIN"
echo "OD_PROJECT_ID=$OD_PROJECT_ID"
echo "OD_PROJECT_DIR=$OD_PROJECT_DIR"
echo "OD_DAEMON_URL=$OD_DAEMON_URL"
ls -la "$OD_BIN"
OD_DAEMON_URL must be a real daemon port such as http://127.0.0.1:7457, not http://127.0.0.1:0. The :0 value is only an internal "pick a free port" launch hint and should not leak into agent sessions.
For the daemon-only production mode, the daemon serves the static Next.js export itself at http://127.0.0.1:7456, so no reverse proxy is involved.
If you place nginx in front of the daemon, keep SSE routes unbuffered and uncompressed. A common failure is the browser console showing net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK) after 80-90 seconds because nginx gzip on buffers chunked SSE responses even when the daemon sends X-Accel-Buffering: no.
location /api/ {
proxy_pass http://127.0.0.1:7456;
proxy_buffering off;
gzip off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Two execution modes
| Mode | Picker value | How a request flows |
|---|---|---|
| Local CLI (default when daemon detects an agent) | "Local CLI" | Frontend → daemon /api/chat → spawn(<agent>, ...) → structured tool/file events over SSE → project files → preview. Plain-stream CLIs use the text-artifact path instead. |
| API mode (fallback / no CLI) | "Anthropic API" / "OpenAI API" / "Atlas Cloud" / "Azure OpenAI" / "Google Gemini" | Frontend → daemon /api/proxy/{provider}/stream → provider SSE normalized to delta/end/error → <artifact> parser → preview |
Both modes end in the same file workspace and sandboxed preview, but their handoff contracts differ. Filesystem-capable runtimes write the canonical files and must not echo their source in <artifact>; plain/text-only and BYOK runs have no file tools, so their canonical deliverable is the complete HTML inside <artifact>. The execution profile is selected from the runtime transport, and local CLIs receive the composed prompt through the invocation shape declared by their runtime definition.
Prompt composition
For every send, the app builds a system prompt from three layers and sends it to the provider:
BASE_SYSTEM_PROMPT (execution-profile-specific file or <artifact> handoff)
+ active design system body (DESIGN.md — palette/type/layout)
+ active skill body (SKILL.md — workflow and output rules)
Swap the skill or the design system in the top bar and the next send uses the new stack. Bodies are cached in-memory per session so this is a single daemon fetch per pick.
File map
open-design/
├── apps/
│ ├── daemon/ # Node/Express — spawns local agents + serves APIs
│ │ └── src/
│ │ ├── cli.ts # `od` bin entry
│ │ ├── server.ts # /api/* + static serving
│ │ ├── agents.ts # compatibility exports for the runtime modules
│ │ ├── runtimes/
│ │ │ ├── registry.ts # supported runtime registry
│ │ │ └── defs/ # per-runtime launch and argument definitions
│ │ ├── skills.ts # SKILL.md loader (frontmatter parser)
│ │ └── design-systems/ # DESIGN.md loader and services
│ │ ├── sidecar/ # tools-dev daemon sidecar wrapper
│ │ └── tests/ # daemon package tests
│ ├── web/ # Next.js 16 App Router + React client
│ ├── app/ # App Router entrypoints
│ ├── src/ # React + TypeScript client/runtime modules
│ │ ├── App.tsx # orchestrates mode / skill / DS pickers + send
│ │ ├── providers/ # daemon + BYOK API transports
│ │ ├── prompts/ # system, discovery, directions, deck framework
│ │ ├── artifacts/ # text-artifact parsing + artifact manifests
│ │ ├── runtime/ # iframe srcdoc, markdown, export helpers
│ │ └── state/ # localStorage + daemon-backed project state
│ ├── sidecar/ # tools-dev web sidecar wrapper
│ └── next.config.ts # tools-dev rewrites + prod apps/web/out export config
│ └── desktop/ # Electron runtime, launched/inspected by tools-dev
├── packages/
│ ├── contracts/ # shared web/daemon app contracts
│ ├── sidecar-proto/ # OpenDesign sidecar protocol contract
│ ├── sidecar/ # generic sidecar runtime primitives
│ └── platform/ # generic process/platform primitives
├── tools/dev/ # `pnpm tools-dev` lifecycle and inspect CLI
├── e2e/ # Playwright UI + external integration/Vitest harness
├── skills/ # functional capabilities invoked mid-task
├── design-templates/ # rendering catalog for prototypes, decks, docs, and media
├── design-systems/ # brand packages rooted at DESIGN.md
├── scripts/sync-design-systems.ts # re-import from upstream getdesign tarball
├── docs/ # product vision + spec
├── pnpm-workspace.yaml # apps/* + packages/* + tools/* + e2e
└── package.json # root quality scripts + `od` bin
Troubleshooting
better-sqlite3fails to load / ABI mismatch after a Node.js version change —pnpm installre-runspostinstallautomatically and rebuilds the native addon for the current Node.js. To rebuild manually or verify the fix:pnpm --filter @open-design/daemon rebuild better-sqlite3thenpnpm --filter @open-design/daemon exec node -e "require('better-sqlite3')". Requires build tools:python3,make,g++(orclang++). If you useignore-scripts=truein your.npmrc(common for AUR packages), runpnpm bootstrapafterpnpm install.- "no agents found on PATH" — install one of the local runtimes registered in
apps/daemon/src/runtimes/registry.ts, make sure its executable is visible to the daemon, then use Rescan in Models & providers → Local CLI. Or configure a BYOK runtime in Settings. - Claude Code exits with code 1 — OpenDesign was able to start
claude, but the spawned non-interactive run failed before producing a response. From the same shell or app environment that starts OpenDesign, check:If the smoke test reportsclaude --version claude auth status --text printf 'hello' | claude -p --output-format stream-json --verbose --permission-mode bypassPermissions401,apiKeySource: "none", or another auth error without a custom endpoint, runclaude, use/login, exit Claude, and retry OpenDesign. If you use multiple Claude profiles, set Models & providers → Local CLI → Claude Code config directory to the profile path such as~/.claude-2. IfANTHROPIC_BASE_URLor a proxy is set, check the endpoint URL, proxy credentials, endpoint auth environment, and model access; remove the custom endpoint only if you want to retry with standard Claude Code auth. On Windows, native PowerShell and WSL use separate Claude installs and credential stores; re-authenticate in the same environment OpenDesign uses, and check Windows Credential Manager if/logindoes not repair native Windows credentials. - daemon 500 on /api/chat — check the daemon terminal for the stderr tail; usually the CLI rejected its args. Different CLIs take different argv shapes; inspect the matching definition in
apps/daemon/src/runtimes/defs/if you need to adjust one. - media generation says
OD_BINis missing or daemon URL is:0— run the media dispatcher checks above. Do not resume the old CLI session; reopen the project from the OpenDesign app so the daemon can inject freshOD_*variables. - Codex loads too much plugin context — start OpenDesign with
OD_CODEX_DISABLE_PLUGINS=1 pnpm tools-devto make daemon-spawned Codex processes run with--disable plugins. - artifact never renders — first identify the run's handoff profile. For a filesystem-capable local runtime, confirm the agent created a previewable project file and that file-write events reached the daemon; it should not emit source in
<artifact>. For a plain/text-only or BYOK run, confirm the response contains one complete<artifact>block. Check daemon logs for the first failed boundary instead of asking a filesystem runtime to fall back to inline source. - Browser authentication prompt on macOS — keep Docker Desktop's default bridge networking. Sign in with username
open-designand theOD_API_TOKENvalue fromdeploy/.envas the password. Host networking is not required. Seedeploy/README.md— Docker Desktop on macOS.
Mapping back to the vision
This Quickstart is the runnable seed of the spec in docs/. The spec describes where this grows (see docs/roadmap.md). Highlights:
docs/architecture.mddescribes the shipped stack: Next.js 16 App Router in front, local daemon behind it, andapps/web/next.config.tsrewrites in dev to keep the browser talking to the same/apisurface.docs/skills-protocol.mddescribes the currentSKILL.md/od:frontmatter and the split between functional skills and rendering templates. The parser and normalization source of truth isapps/daemon/src/skills.ts.docs/agent-adapters.mddescribes the adapter contract. Runtime-specific launch, argument, model, and stream settings live inapps/daemon/src/runtimes/defs/, with registration inapps/daemon/src/runtimes/registry.ts;apps/daemon/src/agents.tsis a compatibility export surface.docs/modes.mddistinguishes the six New Project tabs from the seven normalized registry modes (prototype,deck,template,design-system,image,video, andaudio).