* feat(tools-dev): add --prod flag and OD_HOST for headless server deployment
- Lazy-load electronBinaryPath so daemon+web can start without Electron
- Add --prod flag to tools-dev start/run that sets NODE_ENV, OD_WEB_PROD,
and OD_WEB_OUTPUT_MODE automatically for production Next.js builds
- Add OD_HOST env var support to daemon and web sidecar bind addresses
(defaults to 127.0.0.1, set to 0.0.0.0 for remote access)
- Skip next.config.ts distDir override when OD_WEB_PROD=1 so production
builds resolve the default .next directory
Closes#221
* fix: address PR review — hardcode daemon bind to 127.0.0.1, cache electron path
- Revert OD_HOST from daemon: daemon is a local privileged process and must
only bind 127.0.0.1. Remote access goes through the web sidecar proxy.
- Web sidecar resolveDaemonOrigin now always uses 127.0.0.1, separated from
the web bind address (OD_HOST) so the daemon proxy works correctly even
when the web listener binds 0.0.0.0.
- Add OD_HOST character validation to reject clearly invalid values early.
- Cache electronBinaryPath getter result to avoid repeated require() calls.
---------
Co-authored-by: yamsfeer <yamsfeer@users.noreply.github.com>
Add README.zh-TW.md based on the Simplified Chinese version, converted
via OpenCC s2twp and adjusted to use Taiwan-specific terminology
(備援, 螢幕, 堆疊, 即時, 動態, 計畫, 色票, etc.). Update language
switcher in all existing README variants to include 繁體中文.
* feat(web): pick prompt templates (not design systems) for image/video projects
The New Project panel now shows the curated prompt-template gallery in the
image and video tabs instead of the Design System picker. Design systems
only make sense for prototypes, slide decks, templates, and the freeform
"other" canvas — they don't map onto image/video generation.
The picked template's body is editable in-line ("optimize" affordance) and
the (possibly tuned) prompt is snapshotted into ProjectMetadata as
`promptTemplate`. The system-prompt composer surfaces it on every turn as
a stylistic + structural reference for the agent — same shape we already
use for the saved-template flow.
Also rename the right-side gallery tabs from "Image prompts" / "Video
prompts" to "Image templates" / "Video templates" across all locales.
Made-with: Cursor
* fix(prompt-templates): address review — escape fences, error UI, empty hint, tests
Apply the actionable feedback from the code review:
- Security: escape triple-backticks in `metadata.promptTemplate.prompt`
before interpolating it into the system prompt's fenced block. A user
who pasted ``` into the editable template body could otherwise close
the fence and inject free-form instructions for the agent. Apply the
same fix in both the contracts composer and the daemon mirror.
- UX: surface fetchPromptTemplate failures via an inline error banner
outside the popover, with a one-click retry button bound to the last
failed pick. Previously the error toast lived inside the popover and
vanished as soon as the popover closed.
- UX: show a subtle hint below the prompt textarea when the body is
empty, so users who clear it on purpose understand the agent will
have no template reference.
- Defense in depth: gate the `**referenceTemplate**:` metadata bullet
on a non-empty prompt body in both composers, so a stale title can
never appear in the system prompt without the body it claims to
reference.
- Tests: add tests/system-prompt-template.test.ts covering the happy
path (image + video), the backtick escape, the truncation cap, the
empty-prompt skip, the non-media kinds, and the missing-source path.
- i18n: add `promptTemplates.retry` and `newproj.promptTemplateBodyEmpty`
across all 9 locales; backfill the prompt-template picker keys for
ja, es-ES, de which landed on main after this branch.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: add design-brief skill with structured I-Lang input format
Adds a new skill that accepts structured design briefs (I-Lang protocol
format or natural language) and generates a concrete DESIGN.md with
resolved color, typography, layout, mood, density, and constraint tokens.
Solves the 'make it professional' ambiguity problem by requiring explicit
dimensions. Falls back to sensible defaults for unspecified dimensions
and transparently reports what was assumed.
Outputs: DESIGN.md + optional brief-preview.html showing token swatches.
* fix: add Responsive Behavior and Do's and Don'ts sections to DESIGN.md template
Addresses Codex review: downstream skills (e.g. saas-landing) read
these sections from DESIGN.md. Missing them causes incomplete context.
* fix: address P2 review feedback
- Remove overly broad 'brief' trigger to prevent misfires on
'brief me on X' or 'in brief'. Replaced with 'create a design brief'.
- Add Natural language → I-Lang mapping table (20 common phrases)
so the conversion from vague input to structured dimensions is
explicit, not a black box.
* fix: address all 8 review findings from lefarcen
1. P3 Example values taxonomy: added clarification that values are
representative, not exhaustive. Agent accepts semantically clear
unlisted values, prompts on ambiguous ones.
2. P2 8-dimension justification: added Background section explaining
dimensions derived from analysis of 71 bundled design systems.
Documented why animation/responsive/a11y are excluded at brief level.
3. P2 Symbolic → concrete token resolution: added Section 2.1 with
full mapping table (4 palettes, 3 accents, 3 typography, 3 display,
3 density levels → concrete hex/font/px values).
4. P3 preview.html structure: added 4-section spec (color swatches,
typography specimens, spacing ruler, live component preview).
5. P2 Default resolution logic: added Section 2.2 with mood-aware
default rules for each dimension and static fallback set.
6. P3 design_system.requires inconsistency: changed to requires: true,
generates: true — this skill generates a DESIGN.md from scratch,
and downstream skills require it. Added note about existing
DESIGN.md overwrite/merge prompt.
* fix: clarify typeface limit — mono is utility, exempt from 2-face rule
Resolves contradiction between Do's/Don'ts ('no more than 2') and
DESIGN.md example showing 3 faces (Display + Body + Mono).
* fix: address 3 P3 findings from lefarcen
- Reword 'responsive breakpoints' to 'responsive strategy' in Background,
note DESIGN.md includes sensible breakpoint defaults
- Simplify 'overwrite or merge' to 'overwrite or skip' (merge undefined)
- Add numbering column to 8-dimension table for scannability
* fix: address owner (mrcfps) review — align with OD design-system contract
1. od.mode: prototype → design-system (this skill produces DESIGN.md)
2. design_system.requires: true → false (generates, not consumes)
3. DESIGN.md template uses canonical 9-section OD headings:
- Visual Theme & Atmosphere (NEW)
- Color Palette & Roles (was Color)
- Typography Rules (was Typography)
- Component Stylings (was Components)
- Layout Principles (was Layout)
- Depth & Elevation (unchanged)
- Do's and Don'ts (unchanged)
- Responsive Behavior (unchanged)
- Agent Prompt Guide (unchanged)
4. sections list in frontmatter updated to match
* fix: address 3 contract consistency issues from owner review
1. Remove output_format enum — always generate both DESIGN.md and
brief-preview.html. Prevents manifest advertising a preview file
that may not exist when design_md-only mode is selected.
2. Fix example: typography=inter_for_body → typography=inter.
The example now matches the token resolution table exactly.
3. Make vocabulary closed. Remove 'derive by analogy' instruction
that contradicted Section 3's 'do not invent values outside the
resolution table'. Unknown symbolic values now require user
clarification instead of agent guessing.
* fix: disambiguate mapping table — default to first option when multiple values listed
* fix: add token mappings for all closed vocabulary values
Added concrete tokens for:
- accent=muted_sage (#84A98C) and accent=slate (#64748B)
- typography=dm_sans (DM Sans)
- display=clash_display (Clash Display)
Every value in the vocabulary table now has a corresponding
token-resolution row in Section 2.1. No dead-end paths.
---------
Co-authored-by: adsorgcn <adsorgcn@users.noreply.github.com>
* fix(daemon): clamp codex reasoning effort to model-supported values
Codex's CLI accepts `none | minimal | low | medium | high | xhigh`, but
real models support narrower subsets — picking Minimal in OD's settings
made every chat turn fail with `agent exited with code 1` because the
OpenAI Responses API rejects `reasoning.effort=minimal` on the gpt-5.2
through 5.5 family with `unsupported_value`.
Add a client-side clamp that maps the user's pick to one the chosen
model accepts (Minimal -> low for gpt-5.5 family, xhigh -> high for
gpt-5.1, gpt-5.1-codex-mini caps at medium). Default / unknown model
is treated as gpt-5.5 since that's codex's current default. The user's
UI pick stays valid; the wire request gets a level the model can use.
* docs(daemon): clarify clampCodexReasoning unknown-model behavior
Per PR review — make explicit that unknown / future model ids pass
through unclamped on purpose. The server error then surfaces as the
signal that a new model family rule should be added here, rather than
silently downgrading every unrecognized id.
* test(daemon): cover codex reasoning-effort clamp matrix
Adds a table-driven test in apps/daemon/tests/agents.test.ts that drives
clampCodexReasoning through the public buildArgs surface. The 18 cases
cover:
- minimal -> low for default / explicit gpt-5.2-5.5
- low / medium / high pass-through on gpt-5.5
- xhigh -> high for gpt-5.1
- gpt-5.1-codex-mini cap (low/minimal -> medium, high/xhigh -> high)
- unknown / future models pass through unchanged
- 'default' reasoning omits the -c flag entirely
- path-style model ids (vendor/gpt-5.5-foo) clamp correctly
Tests stay at the wire level (asserting on the args array codex.buildArgs
produces), keeping the helper non-exported and matching the rest of the
file's style.
* docs(daemon): clarify gpt-5.1-codex-mini accepts medium / high
Per PR review — the original "caps at `medium`" wording was misleading
because the clamp returns `high` for `high` / `xhigh` inputs, which
contradicts the comment. The model actually accepts `{medium, high}`,
so describing it as "accepts only `medium` / `high`" matches the
function's behavior.
Logic unchanged.
Claude Code is the last agent that still embeds the composed prompt in
argv (`-p <prompt>`). Composed prompts (system prompt + design system +
skill body + user message) routinely exceed:
- Linux : MAX_ARG_STRLEN ~128 KB per argv entry → `spawn E2BIG`
- Windows: CreateProcess command-line cap ~32 KB direct, ~8 KB via
`.cmd` shim → `spawn ENAMETOOLONG`
the prompt through `child.stdin` (`promptViaStdin: true`). Claude was
explicitly excluded at the time. #97 mitigated the Windows case for
Claude with a `.od-prompt.md` temp-file fallback, but that path still
leaves a stray file in the project, doesn't trigger on Linux, and is
slower than the stdin route the other agents already use.
This change brings Claude in line with the rest:
- Drop the prompt from argv; keep the bare `-p` print-mode flag
- Set `promptViaStdin: true` so server.ts pipes `composed` on stdin
- Add a regression test that asserts the prompt body never lands in
argv even at 200 KB
Verified locally that `claude -p --output-format stream-json --verbose`
(no positional prompt) reads the prompt from stdin under the default
`--input-format text`, which has no length cap.
Fixes#82
Refs #100, #52
Adds three curated first-party video prompt templates to
`prompt-templates/video/`, each with a matching MP4 preview and a
first-frame poster JPG under `assets/prompt-templates/video/`.
These are the direct video companions to the three image templates
opened in PR #207 (Three Kingdoms ARPG screenshot set). Each video
clip is a ~10-12s in-engine cinematic action beat that brings the
corresponding still to life; the two surfaces can be served as a
pair (still → video).
### New templates
1. `video-seedance-three-kingdoms-lyubu-yuanmen-archery.json`
~10s. Lyu Bu (吕布) at the yuanmen between two armies — draws,
holds, releases one gold-qi arrow toward a distant halberd.
Companion to image template
`game-screenshot-three-kingdoms-lyubu-yuanmen-archery`.
2. `video-seedance-three-kingdoms-guanyu-slaying-yanliang.json`
~10s. Guan Yu (关羽) on Red Hare — charges, raises the Green
Dragon Crescent Blade, executes a single clean diagonal cleave
past Yan Liang. No blood on-screen (the strike is implied by a
short gold-into-jade qi flash). Companion to image template
`game-screenshot-three-kingdoms-guanyu-slaying-yanliang`.
3. `video-seedance-three-kingdoms-zhaoyun-cradle-escape.json`
~12s. Zhao Yun (赵云) at Changban — rides with the infant A Dou
cradled in a red silk sling on his chest, parries one incoming
saber with a clean PERFECT DODGE, vaults a fallen war-chariot
and clears a path. Hard safety rail in the prompt: the infant
must stay visible, peaceful and obviously unharmed in every
frame. Companion to image template
`game-screenshot-three-kingdoms-zhaoyun-cradle-escape`.
Each template is tuned for `seedance-2.0`, aspect `16:9`, category
`Cinematic` (reuses the existing category — 17 templates already
live there). Every prompt is explicitly in-engine camera-disciplined
(single continuous beat, no cuts, no slow-motion ramps, no whip pans)
and HUD-free (the companion image template carries the HUD), so
reviewers and downstream users can treat the still + clip as a matched
production pair.
Each template exposes 5-7 `{argument}` slots (reference_image /
environment / hero / weapon / target / mount / qi_color / parry_color
/ infant / attacker as appropriate) so users can restyle the same
shot scaffold for any Three Kingdoms (or, with heavier edits, any
historical battlefield) scene.
### Assets
| File | Size |
| --- | --- |
| `video-seedance-three-kingdoms-lyubu-yuanmen-archery.mp4` | 7.6 MB |
| `video-seedance-three-kingdoms-guanyu-slaying-yanliang.mp4` | 10.3 MB |
| `video-seedance-three-kingdoms-zhaoyun-cradle-escape.mp4` | 11.7 MB |
| 3 × first-frame `-poster.jpg` | 445-527 KB each |
Total: ~30 MB across 3 MP4s, each well under GitHub's 100 MB
single-file limit. Hosted in-repo on `raw.githubusercontent.com`
for a fully self-contained first-party contribution — no external
CDN dependency.
### Verification
- `node -e "JSON.parse(...)"` passes on all three new templates.
- Slugs do not collide with any existing video template on `main`.
- `previewImageUrl` (poster) and `previewVideoUrl` (mp4) both point
at the new in-repo asset paths.
- `source.repo = nexu-io/open-design`, `license = Apache-2.0`,
`author = open-design contributors`, so the first-party guard in
`scripts/import-prompt-templates.mjs` (added in #187) preserves
these across importer re-runs.
### Why
The companion image PR (#207) gives users a beautiful Three
Kingdoms ARPG still they can generate via gpt-image-2; this PR
closes the loop by letting them turn that still into a believable
~10s in-engine clip via seedance-2.0 — the exact production flow
behind the Black-Myth-Wukong-style ARPG demo reel this workstream
is pitching. Paired still + video templates also double as a clean
reference for how first-party `open-design` contributors should
structure a matched set across the two surfaces (same slug suffix,
`companion-to-image` tag, cross-referenced `reference_image` argument,
same hero / environment language, no HUD in the video so HUD can be
sourced from the still).
Co-authored-by: Tuola Ge <gexingli@refly.ai>
Adds one curated first-party image prompt template to
`prompt-templates/image/`, with a matching preview JPG under
`assets/prompt-templates/image/`.
### New template
**`infographic-otaku-dance-choreography-breakdown-gokurakujodo-16-panels.json`**
— A single vertical 2:3 poster composed as a 4x4 grid of 16 connected
square panels, forming a full choreography breakdown chart for the
famous Japanese otaku dance song 極楽浄土 (Gokuraku Jodo).
Each panel shows the same cute half-realistic anime idol girl (pink
twin-tails, sailor-collar school-idol uniform, vivid turquoise eyes)
performing one signature pose from the dance, full-body, on a pastel
pink background with:
- a small Japanese caption strip at the bottom ("両手広げ", "指さし天井",
"ハート手", … "フィナーレ"),
- a numbered circle (1–16) at the top-left corner,
- a clean 4x4 grid with thin black separators,
- an overall header reading "極楽浄土 振り付け 16連動" at the top.
The template is explicitly engineered as a POSE REFERENCE SHEET for
downstream AI video generation — every silhouette is crisp and
unambiguous, no motion lines or background clutter, identical
character across all 16 cells.
Five `{argument}` slots expose song title, romaji, character design,
background color and header text so the same chart can be restyled
for any choreographed dance song while keeping the 16-pose grid
scaffold unchanged. Tuned for `gpt-image-2`, aspect `2:3`. Category:
`Infographic` (reuses the existing enum value; no new enum).
Carries `source.repo = nexu-io/open-design`, Apache-2.0, author
`open-design contributors`.
### Verification
- `node -e "JSON.parse(require('fs').readFileSync('prompt-templates/image/<file>.json','utf8'))"` passes on the new template.
- Slug does not collide with any existing template on `main`, in the
companion Three Kingdoms PR (#207), or in the companion anime
fighting-game PR (#208).
- Preview JPG is 396 KB, comparable to the previews landed in #187.
- `aspect = 2:3` matches the underlying 1024x1536 source render and
the reference-chart layout.
### Why
The existing `Infographic` category has strong timeline/evolution
content (e.g. `3d-stone-staircase-evolution-infographic`) but no
entries aimed at **motion reference** — the one niche where a static
infographic is essentially a production tool for video/animation work.
This template plugs that gap. The 4x4 grid of pose-cells is a
genre-defining layout for dance choreography sheets (used widely for
idol dance covers on Bilibili / YouTube / TikTok) and, because every
cell is a clean, identical-character full-body silhouette on a flat
background, the sheet doubles as a **ready-to-use pose reference**
for AI video pipelines (image-to-video, pose-guided control, keyframe
choreography). One template, two jobs: a pretty poster and a working
production asset.
Co-authored-by: Tuola Ge <gexingli@refly.ai>
Adds one curated first-party image prompt template to
`prompt-templates/image/`, with a matching preview JPG under
`assets/prompt-templates/image/`.
### New template
**`game-screenshot-anime-fighting-game-captain-ryuuga-vs-kaze-renshin.json`** —
A cinematic anime fighting-game key-visual / combat screenshot in the
style of *Street Fighter 6* or *Tekken 8* intro art. Two original
anime-styled male warriors face off at the center of a nighttime
Chinese temple courtyard:
- **Captain Ryuuga (P1)** — shirtless straw-hat pirate with a red
battle-scar, shark-tooth necklace, skull-pattern sash and a warm
orange-red fire aura.
- **Kaze Renshin (P2)** — spiky jet-black hair, orange martial-arts gi
with a single black kanji, charging a crackling blue lightning energy
sphere between his hands.
The background, lighting and warm-vs-cool color grading follow the
rival-fighter convention of the genre (orange left half, blue right
half). The template ships with a complete fighting-game HUD exposed as
slot-filled `{argument}` placeholders:
- Two horizontal health bars with round central round-timer and
`ROUND N` label, per-side HP-percent numerals.
- P1 / P2 portrait panels with character name + subtitle + emblem.
- Per-side `HITS COMBO` counters and max gauges (orange-left,
blue-right).
Ten `{argument}` slots in total make it easy to restyle the matchup
(swap the fighters, backdrop, round number, HP percents, combo counts,
names, titles and emblems) without rebuilding the HUD-and-render
boilerplate. Tuned for `gpt-image-2`, aspect `16:9`. Category: `Game UI`
(reuses the existing enum value introduced in #187; no new enum).
Carries `source.repo = nexu-io/open-design`, Apache-2.0, author
`open-design contributors`.
### Verification
- `node -e "JSON.parse(require('fs').readFileSync('prompt-templates/image/<file>.json','utf8'))"` passes on the new template.
- Slug does not collide with any existing template on `main` or in the
companion Three Kingdoms screenshot PR.
- Preview JPG is 679 KB, comparable to the previews landed in #187.
- `aspect = 16:9` matches the underlying 1792x1024 source render.
### Why
#187 anchored the `Game UI` category with a Chinese MMO HUD mockup.
The companion Three Kingdoms PR extends the category with AAA ARPG
combat-moment screenshots in the Black Myth: Wukong style. This PR
adds a third flavor — an **anime fighting game VS screen** — completing
a compact but representative seed set for the category:
- MMO HUD (UI-heavy scenic moment)
- AAA ARPG (character-driven cinematic combat)
- Anime fighting game (head-to-head VS key visual)
Together these cover three very different HUD conventions and three
different render styles, so downstream users approaching the Game UI
category have a real breadth of starting points to remix from — not
just one aesthetic.
Co-authored-by: Tuola Ge <gexingli@refly.ai>
Adds three curated first-party image prompt templates to
`prompt-templates/image/`, each with a matching preview JPG under
`assets/prompt-templates/image/`.
### New templates
1. **`game-screenshot-three-kingdoms-lyubu-yuanmen-archery.json`** —
Lü Bu drawing a massive recurved warbow at Yuanmen gate to shoot
down a distant halberd at ~150 paces. Over-the-shoulder gameplay
framing with a locked-on target marker and distance readout in the
HUD. Three `{argument}` slots: character, qi_color, setting.
2. **`game-screenshot-three-kingdoms-guanyu-slaying-yanliang.json`** —
Guan Yu riding the Red Hare warhorse through a torrential-rain
battlefield, Blue Dragon Crescent Glaive raised, boss-fight HUD with
a crimson Elite HP bar over the distant enemy general. Four
`{argument}` slots: character, mount, weapon, setting.
3. **`game-screenshot-three-kingdoms-zhaoyun-cradle-escape.json`** —
Zhao Yun at Changbanpo cradling the swaddled infant Liu Chan in his
left arm and sweeping enemies back with a spear in his right, with
a dedicated ESCORT protection bar in the HUD and a visible combo
counter. Four `{argument}` slots: character, child_protected,
weapon, setting.
All three follow the same in-game screenshot recipe: AAA next-gen ARPG
in the cinematic photoreal style of Black Myth: Wukong (with Elden Ring
for the Zhao Yun piece), Unreal Engine 5 Nanite/Lumen rendering, third
person over-the-shoulder camera, and a complete semi-transparent HUD
(portrait + HP/qi bars, minimap, skill hotbar, stamina ring, lock-on /
boss / escort widgets as appropriate). Each ships with a negative
prompt block tuned for this genre — no watermark, no gibberish glyphs,
no cutscene framing, no first-person view, no modern clothing.
All JSONs carry `source.repo = nexu-io/open-design`, Apache-2.0, author
`open-design contributors`, and follow the shape introduced in #187 so
the importer's first-party preservation logic applies unchanged.
Category: `Game UI` (reuses the existing enum value from #187; no new
enum introduced).
### Verification
- `node -e "JSON.parse(require('fs').readFileSync('prompt-templates/image/<file>.json','utf8'))"` passes on all three new templates.
- Slugs do not collide with any existing template on `main`.
- Preview JPGs are 445-527 KB each, comparable to the previews landed in #187.
- `aspect = 16:9` matches the underlying 1536x1024 source renders.
### Why
#187 established `Game UI` as a category with a single HUD-heavy MMO
mockup of a female swordswoman in a scenic shrine. This PR extends the
category with three **combat-moment** screenshots centered on specific
Three Kingdoms heroes in their most iconic scenes — giving the library
a clear complement (character-driven action beats) to the existing
HUD-demo anchor. The Three Kingdoms theme also opens a reusable
narrative scaffold: the `{character}` / `{weapon}` / `{setting}` slot
pattern lets downstream users regenerate the same HUD-accurate gameplay
framing for other Chinese historical figures (e.g. Yue Fei, Huo Qubing)
or wholly custom warriors, without having to rebuild the HUD-and-render
boilerplate from scratch.
Co-authored-by: Tuola Ge <gexingli@refly.ai>
The verify job ran `pnpm typecheck` (root script) which executes
`pnpm -r run typecheck` *before* the daemon build. The e2e workspace's
typecheck imports types from `apps/daemon/dist/*.js`, so on a fresh
clone (every CI run) it fails with TS2307 cannot-find-module.
Drive the order explicitly inside the verify job:
1. install deps
2. build daemon (produces dist/*.js + .d.ts)
3. workspace typecheck
4. check:residual-js
5. workspace tests
This keeps the root `typecheck` script untouched (which other dev /
contributor workflows may depend on) — the workflow simply imposes the
correct order itself. The atomic publish job already prevented orphan
tags/releases when the first dispatch failed at typecheck.
Co-authored-by: Elian <elian@EliandeMacBook-Pro.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(prompt-templates): add dance storyboard and ancient-china MMO HUD templates
- social-media-post-sensational-girl-dance-storyboard-8-shots: 8-shot storyboard
prompt set with shared global style tokens, negative prompt, and character
lock, tuned for GPT-Image-2. Produces a continuous dance choreography as a
coherent 8-frame sequence.
- game-ui-ancient-china-open-world-mmo-hud: HUD mockup for a Black Myth: Wukong
style ancient-China open-world MMO, centered on a female swordswoman
protagonist. Covers character panel, minimap with bagua frame, skill hotbar,
quest tracker, chat window, and world-space nameplates with Chinese
typography rules.
- scripts/import-prompt-templates.mjs: preserve hand-authored templates on
re-run by keeping any JSON whose source.repo is not the upstream CC-BY
corpus. Previously clearDir wiped the whole directory, which would delete
first-party curated prompts on the next import.
Both templates carry source attribution to nexu-io/open-design under
Apache-2.0. Categories reuse the existing 'Social Media Post' and 'Game UI'
enum values already present in the gallery.
* feat(prompt-templates): add preview images for dance and MMO HUD templates
- assets/prompt-templates/image/social-media-post-sensational-girl-dance-storyboard-8-shots.jpg:
an 8-panel storyboard render produced from the template itself, downscaled to
1024x1536 JPEG for gallery thumbnails.
- assets/prompt-templates/image/game-ui-ancient-china-open-world-mmo-hud.jpg:
a reference HUD screenshot rendered from the template prompt via gpt-image-2,
downscaled to 1536x1024 JPEG.
- Both templates now reference these previews via a raw.githubusercontent.com
URL pointing at nexu-io/open-design main, matching the pattern used by the
existing YouMind-sourced seeds (cms-assets.youmind.com) so every card in the
Prompt Gallery carries a thumbnail once the PR merges.
---------
Co-authored-by: Joey <joey@open-design.local>
* docs: add TRANSLATIONS.md i18n contribution guide
Captures the implicit conventions around adding a new locale: which
files to touch (types.ts, locales/, index.tsx, READMEs), how to keep
the language switcher synchronized across all README variants, the
backport policy, and a starter zh-CN ↔ zh-TW glossary extracted from
PR #194.
Resolves the action item from #195. CONTRIBUTING.md cross-links into
this file from its existing "Localization maintenance" section.
The "Open questions" section is intentionally preserved as a signal to
future contributors that translation memory tooling, drift detection,
and freshness badges are live design discussions.
* docs(translations): address review feedback from #196
- Standalone-file rationale: add inline paragraph (lefarcen #196:5)
- Maintained-locales table: add Status column, mark zh-TW README as
in-flight via #194 instead of claiming it exists, clarify ja/ko as
README-only (codex #196:28, lefarcen #196:23)
- Step 4: include the import line + DICTS map example so contributors
don't hit a TS error after copy-paste (lefarcen #196:54)
- Step 6: drop the impossible "order by LOCALES" rule — switcher set is
the union of UI-dict and README-only locales, ordering must just stay
consistent across all READMEs (codex #196:61)
- Backport policy: define a concrete drift threshold (≥20 keys OR
6 months), reference the deferred CI follow-up (lefarcen #196:70)
- Stale-locale signal: add concrete artifacts — table marker +
frontmatter comment (lefarcen #196:77)
- Glossary: split Core (OpenCC-handled) from Idiomatic (judgment calls)
and add the missing rows from #194 — 兜底/活的/計畫/色票/規格文件/介入修正/出包/捆綁→納入
(lefarcen #196:93)
- Native-speaker review: ground "~7 days" as starting point, not hard
policy; move it to Open questions for future tuning (lefarcen #196:128)
- Resolve TM-tooling contradiction by introducing a "Deferred decisions"
section — distinguishes "decided to defer" from "still open"
(lefarcen #196:137)
Add white-space: nowrap to .viewer-action, .viewer-toggle, and .viewer-tab
to prevent Chinese/Japanese text from breaking to a new line when the
toolbar runs out of horizontal space. English text was unaffected because
browsers treat whole words as atomic units, but CJK characters can break
between any two characters by default.
* fix(daemon): add CORS header to raw project file endpoint
srcdoc iframes have a null origin. When preview HTML fetches component
files from /api/projects/:id/raw/*, the browser blocks the response
because the route returned no Access-Control-Allow-Origin header.
Only respond with the header when the request Origin is the string
"null" — the signature of a srcdoc iframe. Real cross-origin requests
from other websites remain blocked, keeping the endpoint safe even if
the daemon is deployed on a remote server.
Fixes#134
* fix(daemon): add CORS header to raw project file endpoint
srcdoc iframes have a null origin. When preview HTML fetches component
files from /api/projects/:id/raw/*, the browser blocks the response
because the route returned no Access-Control-Allow-Origin header.
Only respond with the header when the request Origin is the string
"null" — the signature of a srcdoc iframe. Real cross-origin requests
from other websites remain blocked, keeping the endpoint safe even if
the daemon is deployed on a remote server.
Also add an OPTIONS preflight handler to future-proof the route for
artifacts that may send custom request headers, and add test coverage
for the null-origin allow / real-origin block behaviour.
Fixes#134
---------
Co-authored-by: jiangding001 <jiangding001@ke.com>
* docs(xiaohongshu): address review feedback from #24
Ten review notes from #24, eight applied in this file, one tracked in PR
body, one explicitly deferred per reviewer guidance.
- §2: clarify the brand-red split — the +6 red-channel shift between
#FF2442 (token) and #FF2E4D (component layer) is documented as
intent-undocumented-upstream rather than left implicit.
- §2: add a heads-up that danger reuses --primary, so destructive
actions and primary CTAs are visually identical out of the box;
recommend outline + brand-red text or a leading destructive icon as
a defensive default.
- §2: state dark-mode trigger explicitly (prefers-color-scheme + manual
override; both :root[dark] and .force-dark honored).
- §5: explain *why* the masonry uses translate3d + ResizeObserver
rather than CSS Masonry — the latter is still flagged in most
browsers as of 2026.
- §6: add a dark-mode row to the elevation table; alpha-on-black
shadows are invisible on the #19191E canvas, so drop hover shadows
and replace modal shadow with a 1px hairline at rgba(255,255,255,.07).
- §7: forbid fabricating the 小红书 wordmark / RED logotype as artifact
output (tokens are not protectable, the wordmark is — emit a labelled
grey block instead).
- §7: forbid referencing RED Number standalone in generated CSS without
the PingFang fallback chain.
- §7: add a concrete shadow threshold to the heavy-shadows Don't —
alpha > 0.15 or spread > 16px is the cutoff.
- §9: new "Brand Red Disambiguation" subsection at the top of the Agent
Prompt Guide making the per-surface rule explicit (default: #FF2442;
pixel-replica only: #FF2E4D; never mix on one component).
Schema-drift between CONTRIBUTING.md and the bundled design-system
corpus is intentionally not addressed here — the reviewer flagged it as
a wider-scope cleanup affecting all ~70 systems and explicitly said
"no action requested in this PR" if treated as such.
* docs(xiaohongshu): correct channel-delta in brand-red rationale
Codex review bot caught a numerical error in #54: #FF2442 → #FF2E4D
is not "+6 on the red channel" — both colors share the same red
channel (FF = 255). The actual delta is +10 on green (24 → 2E) and
+11 on blue (42 → 4D), which together raise lightness slightly and
shift the hue a touch toward pink.
Document review badge: P2.
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* chore: update next-env.d.ts route types path
Made-with: Cursor
* docs(readme): refresh stats, agents, skills and add metrics workflow
Make all three READMEs (en / zh-CN / ko) tell the truth about what the
project actually ships, and add lightweight community signals at the top
and bottom.
- Hero block: live for-the-badge GitHub stats (stars, forks, issues,
PRs, contributors, commit activity, last commit) sit directly under
the banner, with the smaller flat-square project-meta row (License,
Agents, Design systems, Skills, Quickstart) below them and the
language switcher below that.
- Counts updated to reality: 31 skills (was 19), 72 design systems
(was 71), 10 coding-agent CLIs + OpenAI-compatible BYOK (was 7).
- "At a glance", architecture, and prompt-stack tables updated to
cover /api/templates, /api/import/claude-design, /api/proxy/stream,
/api/artifacts/lint, sidecar IPC, and per-namespace runtime data.
- New "Beyond chat — what else ships" section covering Claude Design
ZIP import, BYOK proxy with SSRF block, saved templates, tab
persistence, artifact lint, sidecar protocol + headless desktop, and
Windows-friendly spawning.
- Skills tables rebuilt by mode (prototype, deck) and scenario; the
"template" mode claim is removed.
- Supported coding agents table expanded to all 10 CLIs (Claude Code,
Codex, Gemini, OpenCode, Cursor Agent, Qwen, Copilot, Hermes, Kimi,
Pi) plus a BYOK row, with accurate stream formats and argv shapes.
- Roadmap re-flowed to mark shipped vs pending items.
- Contributors wall (contrib.rocks), Repository activity (lowlighter
metrics SVG), and Star History added to all three READMEs, with
cache_bust=2026-04-30 on the contrib.rocks and star-history image
URLs to bypass GitHub camo caching.
- Korean README harmonised end-to-end with the English/Chinese ones.
- New .github/workflows/metrics.yml regenerates
docs/assets/github-metrics.svg daily; ship a placeholder SVG so the
image works before the first scheduled run.
Made-with: Cursor
* docs(readme): address PR #173 review feedback
- Replace invalid 0x14 control character in github-metrics.svg with an
em-dash so the placeholder is well-formed XML and renders as an
image (P1: was breaking SVG parse before the first metrics run).
- Clarify the placeholder SVG subtitle to spell out the token model:
GITHUB_TOKEN gives core stats; METRICS_TOKEN unlocks richer plugins
(traffic, follow-up). Reduces "do I need a secret?" confusion.
- Rewrite the metrics.yml inline auth comment to match: METRICS_TOKEN
is optional and only enables richer plugins; GITHUB_TOKEN is enough
for core metrics. Previous comment read as if METRICS_TOKEN was
mandatory.
- Soften the BYOK fallback row in all three READMEs (EN / zh-CN / ko)
with a catch-all phrase ("or any other OpenAI-compatible provider")
so the listed vendors don't read as exhaustive.
Closes#141.
When the user clicked the Fullscreen button, requestFullscreen() put the
stage element into native browser fullscreen and React's `fullscreen`
state was set true. Pressing Esc was meant to exit the overlay, but in
browsers like Firefox the browser consumes Esc to drop its native
fullscreen element without delivering keydown to JS. The React state
stayed true, the `ds-modal-fullscreen` class lingered, and only a second
Esc reached the keydown handler that flipped the state.
Subscribe to `fullscreenchange` so the React state mirrors the native
state. When the browser exits its fullscreen element, the overlay drops
on the same keystroke. The keydown handler is still needed for the
fallback path (no native fullscreen API support, where requestFullscreen
is undefined and only React state is set).
Adds three regression tests in e2e/tests/preview-modal-fullscreen.test.tsx
covering the bug fix path, the keydown fallback, and a non-collapse
guard for transitions where another element is still fullscreen.
Co-authored-by: d 🔹 <258577966+voidborne-d@users.noreply.github.com>
tools-dev generated a temp web tsconfig with Windows backslash relative paths in extends, which Next/TypeScript failed to resolve in some environments. Normalize runtime tsconfig/dist path strings to POSIX separators so dev config resolution works consistently across Windows/Linux/macOS.
* fix(daemon): preserve non-ASCII filenames on multipart upload
multer@1 hands callers latin1-decoded multipart filenames, and
sanitizeName() then collapses every non-ASCII character to '_'. A
Chinese DOCX uploaded as 测试文档.docx therefore landed on disk as
____.docx, while the response shipped a latin1-mangled originalName
back to the client. The chat composer compared that to the UTF-8
File.name from the picker, missed the match, and reported "some
files could not be stored" even though the bytes were already on
disk.
Add decodeMultipartFilename() that round-trip-checks latin1->utf8
so genuine latin1 names aren't corrupted, and switch sanitizeName()
to keep \p{L}\p{N} (Unicode letters/digits) while still stripping
path separators, control characters, and Windows-reserved
punctuation. Apply the decoder to all three multer storage filename
callbacks so /api/upload, /api/import/claude-design, and
/api/projects/:id/upload all return UTF-8 originalNames.
Closes#144
* fix(daemon): address review feedback on filename decoder
Three changes from review:
1. decodeMultipartFilename now bails out early when any code point in
the input exceeds 0xFF. multer can hand us an already-decoded UTF-8
string when the client uses the RFC 5987 `filename*` parameter, and
the previous round-trip-only check would corrupt those names — for
example, a properly decoded `测试文档.docx` could be re-mangled into
`KՇc.docx` because the latin1-encoded bytes happened to form a
valid UTF-8 sequence. Code points above 0xFF can never appear in a
genuine latin1-decoding-of-utf8 input, so they're an unambiguous
signal that no further decoding should run.
2. decodeMultipartFilename now handles null/undefined defensively (it
was relying on multer always populating originalname; this just
makes the helper safer to reuse from other call sites).
3. The inline sanitiser regex in the `upload` and `importUpload`
multer instances is replaced with a direct `sanitizeName()` call,
matching what `projectUpload` already did. This keeps a single
source of truth for the allowed character set so future tweaks
only have to land in one place.
Adds two more tests to the existing sanitize-name suite covering the
above-0xFF early return and the null/undefined inputs (13/13 in that
file, 58/58 across the daemon).
resolveProjectRoot only stripped a 'dist' suffix from the caller's
module directory, so when the daemon sidecar is started by tools-dev
(which runs apps/daemon/src/server.ts directly through tsx) the
computed PROJECT_ROOT pointed at apps/ instead of the repo root.
That made SKILLS_DIR, DESIGN_SYSTEMS_DIR, STATIC_DIR and the default
RUNTIME_DATA_DIR all resolve to non-existent paths, so /api/skills
returned an empty list and the web "examples" page reported
"No skills available. Is the daemon running?".
Treat 'src' the same as 'dist' so resolution works for both the tsx
source entry and the compiled build, and add a regression test for
the src case alongside the existing dist/daemon-root cases.