Commit Graph
62 Commits
Author SHA1 Message Date
qiongyu1999 c2acb0c864 fix(ve-presets): align preview motion and slideCount with example contracts
Review follow-up for #4127 (mrcfps):
- ve-midnight-editorial / ve-terminal-mono / ve-warm-signal set
  od.preview.motion to "deck" while their example.html files are
  vertical scroll-snap documents; switched to "scroll" so the
  marketplace hover clip traverses them correctly.
- ve-terminal-mono / ve-warm-signal advertised slideCount options
  (5-10 / 10-20 / 20+) that the locked prompt overrode with a hard
  8-11 requirement; the prompt now honors {{slideCount}}, and the
  SKILL.md slide-count rule is rephrased as a default that yields to
  the user's selection.
2026-06-11 18:14:28 +08:00
qiongyu1999 ac2301894d feat(plugins): unify all 30 community deck seeds with the Open Design product narrative
Replace per-deck placeholder content with one canonical 10-section story
sourced from the homepage structure doc and README: cover, why (Claude
Design proved it, OD opens it), three claims, numbers board (60K+ stars /
300+ contributors / 217+ plugins / 129 design systems / 21 agents), 5-step
workflow, multimodal outputs, capabilities, agent ecosystem, testimonial,
and CTA with GitHub/Discord/X links for organic resharing.

Content-only edits: CSS tokens, layouts, decorations, animations, keyboard
nav and hash routing untouched in every deck. huashu-* decks carry the zh
copy; fs-/hps-/ve- decks carry the en copy (latin display faces). All 29
rewrites + 1 pilot verified: script syntax, cover screenshot, no fictional
brand residue.
2026-06-11 12:49:29 +08:00
qiongyu1999 0975f2bce9 feat(plugins): add 30 community slides/deck plugins from top open-source slides skills
Convert the highest-starred MIT-licensed slides skills into community deck
plugins (one template style = one plugin), plus 3 family root plugins:

- frontend-slides (zarazhangrui, 21.1k stars): root + 7 style variants (fs-*)
- huashu-design (alchaincyf, 18k stars): slides cut root + 8 variants (huashu-*)
- html-ppt-skill (lewislulu, 5.8k stars): root + 9 theme variants (hps-*)
- visual-explainer (nicobailon, 8.7k stars): 3 aesthetics (ve-*)

Each plugin ships the standard trio (open-design.json + SKILL.md locked spec +
self-contained example.html seed, zero external JS), validated against
PluginManifestSchema. All 30 registered in the community marketplace registry
(0.1.2 -> 0.2.0). Every variant was deduped against the 59 existing official
deck plugins (zhangzara ports, guizang, html-ppt family) before inclusion.
Upstream attribution preserved: MIT LICENSE files + author/homepage per plugin.
2026-06-11 12:06:15 +08:00
b034609cde chore(plugins): remove the shamoni example plugin (duplicate preview imagery) (#4040)
* chore(plugins): remove the shamoni example plugin

The Shamoni scroll-driven gallery example ships a baked preview that
duplicates luxury-botanical's hero imagery, so the Community shelf
shows the same perfume tile twice. Curator call: drop the example
entirely — plugin folder, baked-preview manifest entry, and its slot
in the pinned curated ordering.

* fix(daemon): prune persisted bundled rows when their folder leaves the image

The bundled boot walker only upserted folders that still exist, so a
plugin removed from the daemon image (like the Shamoni example this PR
deletes) survived in upgraded installs' installed_plugins table — and
/api/plugins kept serving a record whose backing files were gone.

Make bundled rows mirror the bundled tree: after a successful walk,
delete source_kind='bundled' rows whose folder was not seen this boot.
Folders that still ship but fail to parse stay registered (warned, not
pruned), the ENOENT early-return never prunes (a missing bundledRoot is
a packaging bug, not a removal), and user-installed rows are untouched.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-10 08:07:12 +00:00
ec47346e94 feat(web): composer 插件菜单 & 设计百宝箱 hover 预览 (#4000)
* feat(web): hover-preview column in the composer plugins menu

Hovering (or arrow-defaulting to) a plugin in the composer "+" → Plugins
flyout now opens a second-level preview column: a live preview hero
(reusing the plugins-home PreviewSurface — media poster or sandboxed
example iframe) plus the localized title, trust badge, description, and
tags. The previewed row stays highlighted so the panel's subject is
clear before the cursor lands.

The Plugins flyout widens to fit the side column and reserves that width
in the placement math; on narrow (contained) surfaces the preview drops
below the list instead. Other submenus are unchanged.

* feat(web): design-toolbox hover preview + styled detail panel

Extends the plugin hover-preview to the project composer's design
toolbox. Hovering a plugin entry now renders the same rich preview
(ComposerPluginPreview — poster / sandboxed example iframe + title,
trust badge, description, tags); every other kind (skill, MCP,
connector, file, follow-up action) keeps a compact text card.

The shared hover-detail panel (.plus-menu__detail) previously shipped
with no CSS at all — it had no position/background/border, so the
inline left/top never applied. This adds the panel styling (fixed,
panelled, shadowed, viewport-clamped) plus the section-label and
detail text styles, and clamps the panel's top so the taller plugin
preview stays on screen. ComposerPluginPreview's column divider was
de-scoped to the plugins-flyout context so it renders cleanly inside
the toolbox panel too.

* fix(web): drop redundant divider above design-toolbox search

The toolbox head carried a border-bottom while the search box below it
has its own full border, so with the flyout gap the two hairlines read
as a doubled line. Drop the head border; the search box already bounds
the section.

* fix(web): localize plugin titles in the composer plugins list

The list rendered the raw `plugin.title` (often English) while the
hover preview used the localized `title_i18n`, so the same plugin showed
two different-language names side by side. Render the localized title in
the list too, and fold it into the search haystack so a localized-name
query still matches.

* feat(web): show plugin kind tag in the hover preview

Adds a localized kind pill (Prototype / Slides / Image / Video / Audio /
HyperFrames / Live artifact) to the plugin preview title row, reusing
extractCategories — the same taxonomy that powers the home Community
filter chips — so the preview names the plugin's type at a glance. Shows
in both the composer plugins menu and the design-toolbox preview.

* fix(web): localize the applied-plugin chip title

The composer's applied-plugin chip showed the raw `record.title` (English,
e.g. "Audio Jingle") while the same plugin's preset card / hover preview
used the localized `title_i18n` (e.g. "音频铃声"), so the two read in
different languages. Localize the chip in both surfaces:
- HomeView: activeBadgeTitle now uses localizePluginTitle(locale, record).
- PluginsSection: the ContextItem label (project ChatComposer chip) too.

Mirrors the already-correct PluginPromptPresetCard pattern.

* fix(web): localize trust badge, drop raw tag chips from preview

- TrustBadge now resolves its label via i18n (pluginsView.trust.*) so
  Official / Trusted / Restricted follow the active locale everywhere it
  renders; an explicit `label` prop still overrides.
- Drop the raw manifest tag chips from the plugin hover preview. Tags are
  author-defined English slugs with no controlled vocabulary, so they
  can't be reliably localized; the localized kind pill already conveys
  the category, so the card stays single-language.

* feat(web): tag design-system plugins in the hover preview

Design-system plugins aren't one of the home Community facets, so
extractCategories returns nothing and they had no kind pill. Detect them
by mode/tag (same heuristic as the preview classifier) and show the
localized 'Design systems' label (entry.navDesignSystems).

* i18n(plugins): backfill title/description translations for 22 example plugins

These 22 official example manifests shipped title_i18n / description_i18n
with only zh-CN + en, so in every other UI language (Korean, Japanese,
…) the plugin name and description fell back to English — visible now
that the composer surfaces them in the hover preview.

Fill all to the full 18-locale set (zh-CN, zh-TW, ja, ko, de, fr, ru,
es, pt-BR, it, vi, pl, id, nl, ar, tr, uk, en), matching the locale set
used by the already-complete manifests. Brand/product/proper names and
technical terms are kept verbatim; useCase.query stays English-authoritative.

* fix(web): clamp design-toolbox detail panel into the viewport

The left-side fallback (when the right side overflows) used
rect.left - gap - detailWidth without clamping, so a row near the left
edge or a pane narrower than detailWidth + gap*2 produced a negative
left and pushed the position:fixed panel off-screen. Clamp the chosen
left into [8, innerWidth - 8 - detailWidth] so it always degrades
gracefully. (review: nettee/looper)

* test(web): extract + unit-test toolbox detail panel positioning

Pull the detail-panel placement out of showToolboxDetail into a pure
computeToolboxDetailPosition helper and pin the narrow-pane clamp with a
focused vitest regression (row near left edge / viewport narrower than
the panel never yields a negative left; top clamps too). Addresses the
nettee/looper review ask for a regression check.

* fix(web): match plugins-flyout placement reserve to rendered width

PLUS_MENU_PLUGIN_FLYOUT_WIDTH was 560 while .plus-menu__flyout--plugins
renders at 466px, so getFlyoutPlacement over-reserved and medium-width
panes (~664-757px side room) wrongly fell back to the contained layout,
silently dropping the side-by-side preview column. Set it to 466 (with a
cross-reference comment to the CSS), extract the boundary arithmetic into
a pure resolveFlyoutSide helper, and pin the 466-vs-560 boundary with a
vitest regression. (review: nettee/looper)

* fix(web): localize trust badge tooltip + aria text

title and aria-label still came from the hard-coded English
meta.description, so on non-English locales the badge read as
mixed-language to tooltips and screen readers. Resolve all of label,
title, and aria-label from the localized tier key. (review: nettee/looper)

* fix(web): update TrustBadge test for localized a11y text

The existing TrustBadge spec asserted the old hard-coded English
descriptions ("Open Design official", aria "…: Action plugin"), which the
localization change replaced — that's why Web workspace tests went red.
Keep a localized tier prefix in the accessible text when a contextual
label is passed ("Official: Action plugin") and update the spec to pin
the localized behavior.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-09 17:04:11 +00:00
28f5516697 feat(prompt-templates): add desk hologram AR realdesk Seedance 2.0 video template (#3967)
* feat(prompt-templates): add desk hologram AR realdesk Seedance 2.0 video template

Ship the two-phase keyframe + i2v workflow behind blue-warrior-realdesk-t2v-15s
as a first-party video prompt template with preview MP4/poster and plugin bundle.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(prompt-templates): host desk-hologram previews on repo-assets CDN

Drop the 8.9 MB tracked MP4 to satisfy the 1 MiB blob guard and point
previewImageUrl/previewVideoUrl at repo-assets.open-design.ai, matching
the Three Kingdoms Seedance templates. Bump bundledPreinstallCount to 402.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: add workflow to publish prompt-template previews to repo-assets R2

Maintainer workflow_dispatch helper for template PRs that drop large MP4s
from git and point preview URLs at repo-assets.open-design.ai.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: auto-publish desk-hologram template previews on workflow push

Run the repository-assets upload when this workflow lands on the
template branch so PR #3967 preview URLs go live without waiting for main.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: keep repository-template asset publish as workflow_dispatch only

Assets for PR #3967 are live on repo-assets; drop the one-shot branch push
trigger now that the upload succeeded.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(plugins): add specVersion to desk-hologram video template manifest

Align open-design.json with the official video-template plugin schema.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Tuola Ge <gexingli@refly.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 12:16:49 +00:00
b8489c9874 fix(plugins): pin the Motion React UMD loader in motionsites plugins (follow-up to #3973) (#3992)
* fix(plugins): pin Motion React UMD loader in plugins, generalize the system-prompt rule

PR #3973 patched the blank-screen crash (Motion React hooks loaded from the
vanilla motion.js DOM bundle) at the runtime/write boundary and added a
Framer Motion note to the official system prompt. This closes the remaining
gaps:

- Root cause was in the plugins, not just the runtime: the 25-plugin
  motionsites batch (#3873) prescribes Framer Motion hooks in the React port
  but never locks how to load them, exactly as it locks fonts/colors/asset
  URLs. Add a "Motion loading (locked)" note to the 8 plugins that genuinely
  prescribe Framer Motion (3d-creator-portfolio, acreage-farming,
  evergreen-finance, liquid-glass-agency, luxury-botanical, mindloop-landing,
  portfolio-cosmic, shamoni). Plugins that map useScroll *down* to a passive
  listener, or use GSAP only (cinematic-landing-page), are intentionally left
  untouched.
- Generalize the system-prompt note to lead with the principle (two UMD
  builds: vanilla DOM vs React, hooks live only on the React build's
  window.Motion) while keeping one pinned example version.
- Add port-path regression coverage for the reported luxury-botanical plugin:
  full Motion hook set (useScroll/useTransform/useAnimationFrame/useMotionValue),
  the minified vanilla bundle, and the wrong-bundle + FramerMotion-global combo.

Validation: pnpm guard, contracts + daemon typecheck, daemon
artifact-runtime-compat.test.ts (8/8).

* fix(daemon): widen Motion UMD normalizer to jsdelivr + wrong-file shape

The runtime normalizer only matched the exact unpkg `motion@VER/dist/motion.js`
script shape, so two real agent outputs still slipped through to a blank screen:
a vanilla bundle served from jsdelivr, and the right package name pointing at the
wrong file (`framer-motion@VER/dist/motion.js`). Widen the matcher to both hosts
and both package spellings, preserve the original CDN host on rewrite, and
document the `<script src>`-only boundary (ESM imports / importmaps / esm.sh are
steered by the prompt + plugin notes, not rewritten). The React-hook usage gate
still keeps animate-only vanilla DOM artifacts untouched, and a new test pins
that the correct framer-motion.js bundle is never falsely rewritten.

---------

Co-authored-by: audit <a@b.c>
2026-06-09 10:26:06 +00:00
chaoxiaocheandGitHub 25b98195b4 Refine Share to Open Design next step action (#3965)
* Refine Share to Open Design next step action

* fix(web): keep share to OD busy state anchored
2026-06-09 07:04:44 +00:00
b144df3fba fix: restore default scenario craft rails (#3878)
* fix: restore default scenario craft rails

* fix: freeze plugin craft on snapshots

Generated-By: looper 0.9.7 (runner=fixer, agent=opencode)

---------

Co-authored-by: audit <a@b.c>
2026-06-09 01:49:35 +00:00
75f1472d53 feat(web): align Home composer facet rails with Community + drop 6 low-quality example templates (#3939)
* feat(web): align Home composer facet rails with Community + drop 6 low-quality example templates

Home composer sub-category rails now mirror the Community plugin grid
exactly — same sub-category set, order, and per-facet plugin slice:

- Prototype order: Landing/marketing, Brand/design, Dashboards, Apps,
  Developer tools, Docs/reports
- Slides order: Creative decks, Engineering talks, then Pitch/business,
  Course/training, Reports/briefings, Product/sales
- Sub-chips are derived from the full install set (not the curated
  example subset), so the rail shows every type Community shows
- Selecting a sub-category now lists the same plugins Community lists for
  it via applyFacetSelection (primary-category + sub-category match), so
  the example-prompt count matches the Community count badge

Also removes six example templates with broken/poor visuals (Art Landing,
Prisma Creative Studio, Urban Jungle, Modern Agency, AI Automation,
FlowMate) and their pinned-order entries in curatedPriority.

* fix(web): separate facet display order from matching precedence

Addresses review: reordering SUBCATEGORIES re-bucketed overlapping-tag
plugins because extractSubcategories() resolves via SUBCATEGORIES.find()
(first match wins). Dashboards/app/launch-deck plugins with secondary
design/marketing tags wrongly moved into Brand / design or Creative decks
in both Home and Community.

- Restore SUBCATEGORIES to its original matching precedence (stable buckets)
- Add SUBCATEGORY_DISPLAY_ORDER, applied in buildSubcategoryCatalog, so the
  rails/catalog render Landing/Brand/... and Creative/Engineering/... first
  without changing which bucket a plugin lands in
- Add regression coverage in plugins-home-facets.test.ts for overlapping-tag
  fixtures (dashboard+design, mobile+design, landing+brand, launch+marketing,
  pitch+marketing) and update the display-order expectations

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-08 17:56:31 +00:00
bad35b45c9 fix(daemon): stabilize HyperFrames render handoff (#3882)
* fix(daemon): stabilize hyperframes render handoff

* fix: align hyperframes skill handoff guidance

---------

Co-authored-by: audit <a@b.c>
2026-06-08 08:15:58 +00:00
a93869ee09 feat(plugins): 25 motionsites example plugins + daemon asset cache (#3873)
* feat(plugins): add 25 motionsites example plugins + daemon asset cache

Add 25 first-party example scenario plugins under
plugins/_official/examples/ (packaged from motionsites.ai templates via the
motionsites-to-open-design-plugin skill): each ships open-design.json,
SKILL.md, and a self-contained rendered example.html fidelity seed. All 25
pass PluginManifestSchema.

Their cross-border CDN images/videos (cloudinary, higgs.ai, motionsites,
cloudfront) are mirrored to Cloudflare R2 (plugin-assets.open-design.ai) and
high-fidelity compressed (732MB -> 302MB), so example.html / query / SKILL.md
reference the fast public origin instead of slow cross-border hosts.

Daemon asset cache (plugin-asset-cache.ts + /api/asset-cache): a same-origin
disk-cached proxy for any external preview media that remains. The preview
URL rewriter now routes external media (src/poster attrs, CSS url(), and JS
string constants) through it, so cross-border assets satisfy the sandbox CSP
(img-src 'self') and load from local cache. SSRF-guarded: http(s) only, no
credentials, and every resolved address must be public.

* fix(asset-cache): tie SSRF validation to the actual outbound connection

The previous guard resolved DNS in assertSafePublicUrl and then let fetch()
resolve again independently, so a DNS-rebinding host could pass the validation
lookup with a public address and steer the real connection to a private one
(e.g. 169.254.169.254). Move the authoritative check to a connection-time
undici Agent lookup (createValidatingLookup): the address that is validated is
the exact address the socket connects to, closing the TOCTOU gap.
assertSafePublicUrl is now a cheap up-front reject (scheme / credentials /
localhost / literal private IP) only. Adds createValidatingLookup unit tests
(public pass, rebinding-to-private reject, all:true any-private reject).

* fix(asset-cache): reject IPv4-mapped IPv6 literals in the private-IP guard

Node's URL parser normalizes a bracketed mapped literal like
`http://[::ffff:127.0.0.1]/` to the hex form `::ffff:7f00:1`, which the old
dotted-decimal regex missed — so a literal mapped host slipped past
assertSafePublicUrl (and literal IPs skip the DNS lookup hook), letting
`/api/asset-cache` target loopback/private IPv4 via its mapped representation.

Canonicalize IPv6 now: expandIpv6() folds `::` compression and any embedded
dotted IPv4 into eight 16-bit groups, and isPrivateAddress() detects the full
`::ffff:0:0/96` mapped range (hex or dotted), feeding the embedded IPv4 back
through the v4 private-range checks. Group-based classification also replaces
the prefix string-matching for ::, ::1, fe80::/10, fc00::/7, ff00::/8.
Regression coverage added for ::ffff:7f00:1 / ::ffff:127.0.0.1 and
http://[::ffff:127.0.0.1]/x.png.

* fix(asset-cache): full link-local range + stream-cap the upstream body

Two SSRF/DoS hardening fixes on the cache path:

- Link-local was matched as the single fe80:: prefix, leaking the rest of
  fe80::/10 (fe90::, febf::, …) through as "public". Classify with a mask
  ((groups[0] & 0xffc0) === 0xfe80); ULA/multicast use masks too now.

- maxBytes was not a hard ceiling for responses without a trustworthy
  Content-Length: arrayBuffer() buffered the whole body before the size check,
  a memory-exhaustion path for a caller-supplied proxy. Stream the body and
  abort the moment the accumulated size exceeds maxBytes, before concatenating.

Tests: fe80::1 / fe90::1 / febf::1 rejected; a no-Content-Length 800-byte
stream against a 16-byte cap rejects with 413 after <10 pulls (proves it stops
reading instead of buffering the full body).

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-08 07:31:41 +00:00
PerishFireandGitHub 10dfd32a3e Revert "feat: add screenshot-based visual validation to critique loop (#3660)" (#3865)
This reverts commit 931780c914.
2026-06-08 06:24:44 +00:00
netteeGitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
931780c914 feat: add screenshot-based visual validation to critique loop (#3660)
* feat(daemon): add visual validation atom

Generated-By: looper 0.9.3 (runner=worker, agent=codex)

* fix(daemon): fail closed in visual validation

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): narrow visual validation defaults

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): add visual validation to default critique stages

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): harden visual validation review fixes

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): fail closed in visual validation discovery

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* test(daemon): tighten visual validation discovery regression

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): match visual validation reference viewport

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): tighten visual validation capture flow

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): fail closed across visual validation refs

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): honor metadata entry file in visual validation

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): capture visual validation through preview route

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): fail closed without preview context

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): disable pre-start visual validation worker

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): narrow visual validation spec discovery

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): stop advertising visual validation as runnable

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): restore visual validation critique worker

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): delay visual validation until run success

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* test(daemon): cover post-run visual validation scheduling

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): gate post-run visual validation before finish

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* chore(nix): refresh pnpm deps hash

* fix(daemon): preserve deferred pipeline ordering

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(packaging): bundle Chromium for visual validation

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(scenarios): keep visual validation out of default critique loop

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(packaging): bundle Playwright headless shell

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(packaging): invalidate Playwright resource cache

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* fix(daemon): include visual-validation in bundled atom roster

Generated-By: looper 0.9.3 (runner=fixer, agent=codex)

* chore(nix): refresh pnpm deps hash

* fix: restore pre-run plugin surfaces and nix hashes

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

* fix: preserve pre-run surfaces and tolerate headed-only chromium bundles

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

* fix: launch visual validation with bundled chromium

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

* fix: avoid Playwright fixture teardown races

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

* fix: fail packaged visual validation on shell-only chromium

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

* fix: isolate synthetic Playwright test bundles

Generated-By: looper 0.9.5 (runner=fixer, agent=codex)

---------

Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-06-08 04:03:43 +00:00
df9ec8f40d examples: add 3D creator portfolio and Velar luxury real-estate templates (#3817)
* examples: add 3D creator portfolio and Velar luxury real-estate templates

Two first-party motionsites.ai template seeds under plugins/_official/examples/,
each shipping the manifest + locked SKILL.md spec + a self-contained rendered
example.html fidelity anchor.

- example-3d-creator-portfolio: dark gradient-text hero with a magnetic 3D
  portrait, scroll marquee, char-reveal About, and sticky-stacking project cards.
- example-velar-luxury-real-estate: typewriter preloader, scroll-driven building
  that scales up while pinning to a dark stats band, count-up stats, and a
  hover-expand video gallery.

Fixed decoration/portrait images are inlined as compressed WebP data URIs so the
card and detail previews never break in the sandbox; large GIFs/videos and stable
-CDN backgrounds stay as remote URLs. Both manifests validate against
PluginManifestSchema (od.kind=scenario).

* examples: use first-party metadata for motionsites templates

Align the 3D creator portfolio and Velar manifests with the
first-party metadata contract used by the rest of
plugins/_official/examples/** (MIT, author Open Design, repo homepage)
instead of CC-BY-4.0 / third-party motionsites provenance.

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

* examples: point all inlined-asset references in the locked query at example.html

The per-section spec in od.useCase.query.en still named the original remote
hosts (figma.site portrait/decorations, cloudinary HOUSE_IMG) as the asset
source, while only the trailing note said to reuse the inlined data URIs. Since
the query is the authoritative generation brief injected on Use, a port could
copy the deprecated remote URLs and regress to sandbox-403 / broken images.

Rewrote those references to instruct reusing the inlined data:image/webp URIs
from example.html. Genuinely-remote assets on stable CDNs (the 21 motionsites
marquee GIFs, 9 higgs project images, 5 cloudfront gallery videos, the higgs
hero background) are unchanged.

* examples: align Velar nav dark-section refs in the locked query with the seed

The Fixed Navigation bullet in od.useCase.query.en said the nav-color logic
watches "Section 4 and Section 5", but the seed and SKILL.md define the dark
sections as Section 5 (dark statement band) and Section 6 (gallery). Since the
query is injected as the generation brief, the stale ref could make a port watch
the wrong sections and leave the nav dark over the gallery. Updated the string
to match the seed/skill wording.

* examples: give the 3D portfolio nav links real anchor targets

The hero nav shipped #price and #contact links with no matching ids in the
seed, so half the navbar did nothing in the preview (and ports would inherit
the dead links). Added id="price" to the Services section and a minimal
contact footer (id="contact") so all four nav anchors resolve to real targets.
The four-link names stay as the prompt specifies; only the seed gains anchors.

* examples: document the 3D portfolio contact footer in the locked query and skill

The previous fix added a #contact footer to example.html but left the injected
query and SKILL.md describing only five sections (no contact target), so a port
could still recreate a dead #contact anchor. Added the Contact footer section to
the SECTION ORDER, a nav→anchor mapping (every link must resolve), and a Contact
Section spec in both od.useCase.query.en and SKILL.md so the prompt, skill, and
seed all agree.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-07 15:08:47 +00:00
0d84245b98 feat(plugins): add Dashboard UI — Liquid Glass first-party prototype preset (#3779)
* feat(plugins): add Dashboard UI — Liquid Glass first-party prototype preset

Bundle a premium liquid-glassmorphism conference dashboard as an official
example prototype plugin. Picking it routes the plugin as the active driver and
reproduces the template: dual theme-swapped fullscreen background videos, a 4x2
glass/solid card grid, animated voice-wave participant indicators, and a
floating control bar.

- od.kind: scenario with its own generate pipeline (file-write + live-artifact)
  and the full build spec in od.useCase.query so the agent reproduces the design.
- Ships a rendered, self-contained example.html seed as the fidelity anchor and
  the HTML preview entry; the marketplace card uses the motionsites animated
  webp poster.
- All 30 avatars are inlined as base64 SVG data URIs so the preview never breaks
  on external avatar-host rate limits inside the sandbox; background videos and
  screen-share thumbnails stay on stable CDNs.

* fix(plugins): make dashboard-ui-glass avatar instructions consistent with the inlined seed

The top-of-file "Avatars (critical)" rule says to keep the bundled data: URI
avatars, but the Profile button and Meeting alert bullets still named
api.dicebear.com remote URLs — conflicting guidance that could lead a
React/Vite export to ship broken sandbox avatars. Both bullets now say to
reuse the corresponding inlined avatar from example.html.

* fix(plugins): drop dashboard-ui-glass zh-CN query override so it falls back to the full English brief

resolvePluginQueryFallback picks od.useCase.query['zh-CN'] ahead of the English
fallback, so the shortened Chinese string became the entire generation brief for
zh-CN users — dropping the locked avatar/network rules, the card-by-card layout,
and the interaction details the English brief carries, and producing a
materially different dashboard under a Chinese locale. Remove the zh-CN query
override so Chinese users fall back to the authoritative, complete English brief.
title_i18n / description_i18n (marketplace display strings) are unaffected.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-06-06 08:36:14 +00:00
2569f4eba9 feat(scenarios): od-share-to-community skill + post-completion Share button (#3657)
* feat(scenarios): add od-share-to-community plugin + Share to Open Design button

After the user finishes a generation, they currently have to re-prompt the
agent to package what they just made. This adds a quiet "Share to Open
Design" pill in the assistant-completion-row — same area as the
post-feedback Discord prompt — that injects a single trigger prompt
into the chat and lets the bundled `od-share-to-community` scenario
auto-derive the manifest from `*.artifact.json`, `brand-spec.md`, and
the workspace files instead of asking the user fields the project
files already answer.

The skill mirrors `home-hero/plugin-authoring.ts`'s constraint surface
verbatim: no chained CLI suggestions, no `jq` dependency (not in the
agent runtime baseline), and after `od plugin install --source`, point
the user at the existing 3-button plugin-folder card (Add to My plugins
/ Publish repo / Open Design PR) instead of recreating those flows
freeform — the source of bug #2332.

Verified end-to-end via headless browser:
- daemon registers the bundled scenario at /api/plugins
- button renders in the live DOM, gated on (isLast && showFeedback)
- click fires POST /api/runs with the trigger prompt as a user message
- Claude Opus picks up the prompt and starts the share flow

* fix(web): debounce share to open design action

* fix(plugins): register share community scenario pipeline

---------

Co-authored-by: kokisanai <kokisanai@users.noreply.github.com>
Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-05 08:09:04 +00:00
lefarcen fa59871428 Merge origin/main into release/v0.9.0 — back-merge to reconcile v0.9.0 with main
Syncs release/v0.9.0 with main so PR #3282 (release/v0.9.0 → main) merges
cleanly. 17 conflicts resolved by commit-time + per-area ownership:

- Comment/edit/preview: keep main (newer). FileViewer combines main's #3438
  (pin manual-edit inspector, no full-height panel) + #3347 deck/queue work
  WITH release's #3401 hover-card anti-flicker grafted on; #2879 Button kept.
- Toolbar: footer layout (reviewer-validated, ca03a7e0f) overrides main #3447 —
  CLI/agent selector in the composer footer, settings gear in the header, no
  settings item in the AvatarMenu dropdown.
- AMR: keep release's client-side model polling (mergeAmrModelsIntoAgents) and
  all release AMR fixes (#3450 sign-out, #3504 console, #3487 acp tool-only
  guard, amrCloudVisible onboarding, #3511 analytics provider id).
- Pet composer button stays removed (release decision); only /pet slash props
  retained.
- Pickers: main's providerModelsCache approach.

Validation: web typecheck + guard + full web suite (2638) + daemon suite green.
2026-06-03 17:21:00 +08:00
PerishFireandGitHub c3c356961b chore: move large repository assets to r2 (#3492) 2026-06-02 10:19:12 +00:00
d065b50c4c feat(plugins): add Hallmark community skill (#3479)
Co-authored-by: tuolaji <tuola@tuolajideMacBook-Air.local>
2026-06-02 07:49:33 +00:00
d285cb373a feat(daemon): per-agent MCP installer — plugin marketplace + 14-agent planner (#3442)
* feat: add per-agent MCP installer with source-deploy fallback

Wire Open Design's stdio MCP server into 14 coding agents via a single
`curl ... | sh -s <agent>` command. Two paths, chosen automatically:

  Path 1 — a local `od` is found (PATH, packaged app, prior build):
           register the agent via `od mcp install <agent>`.
  Path 2 — no `od`: deploy from source (clone + pnpm install + build +
           link + background daemon), then register.

- od mcp install <agent>: per-agent planner with cli/json/manual
  strategies; resolves the launch spec from the running daemon and
  falls back to a default stdio spec when offline.
- install-agent.sh: POSIX sh bootstrap that locates or source-deploys
  `od` before forwarding; probes past the Unix octal-dump `od`.

* feat(installer): support OD_REF to pin clone branch for source deploy

* fix(installer): fail clearly when OD_HOME is a non-empty non-checkout dir

* fix(installer): place server name before -e flags for claude mcp add

claude's `mcp add` treats `-e/--env` as variadic (`<env...>`), so emitting
`-e KEY=val <name> --` made the CLI swallow the server name as an env value
("Invalid environment variable format: open-design"). Put the name first,
then env flags, then `--`, matching `claude mcp add <name> -e K=v -- <cmd>`.

* feat(plugins): claude/codex one-command install via plugin marketplace; drop install.sh

The install.sh route was load-bearing on a non-existent URL: PR body
advertised `curl -fsSL https://open-design.ai/install.sh | sh -s <agent>`
but Vercel serves the Next.js index page at `/install.sh`, not the
shell script. Bootstrap users got 173KB of HTML piped into sh and
nothing installed.

Re-scoped per maintainer call (lefarcen, 2026-06-01): drop the
self-deploy path entirely, assume the user installs `od` themselves
(brew / npm / DMG), and focus PR #3431 on the one-thing it
genuinely owns — wiring `od mcp` into the user's coding agent.

## Two install paths now

  Agent             User runs
  ───────────────── ──────────────────────────────────────────────────────
  claude            claude plugin marketplace add nexu-io/open-design
                    claude plugin install open-design@nexu-io/open-design

  codex             codex plugin marketplace add \
                       git@github.com:nexu-io/open-design.git
                    codex plugin install open-design@nexu-io/open-design

  cursor / copilot  od mcp install <slug>
  cline / opencode  (writes the agent's own JSON config — see
  openclaw / etc.    apps/daemon/src/mcp-agent-install.ts for the 14
                     supported agents)

Both paths land on the same launch spec: `od mcp --daemon-url <url>`
running as a stdio server, with whatever env the local daemon hands
back from /api/mcp/install-info. The plugin manifest hard-codes
`command: "od"` so it depends on `od` being on PATH — the maintainer's
existing install (brew/npm/DMG) is the source of truth, plugin install
is purely the wiring.

## What this commit does

- Delete deploy/scripts/install-agent.sh (~240 lines) — load-bearing
  but unreachable (Vercel doesn't serve it), and the source-deploy
  path it gated (clone / pnpm install / build daemon / link bin) is
  out of PR scope per the re-scope above.
- Add .claude-plugin/marketplace.json — owner=nexu-io, exposes
  open-design plugin at ./plugins/open-design.
- Add plugins/open-design/.claude-plugin/plugin.json — name +
  displayName + description + mcpServers pointer to .mcp.json.
- Add plugins/open-design/.mcp.json — stdio server `od mcp
  --daemon-url http://127.0.0.1:7456`, same shape /api/mcp/install-info
  hands back.

The TypeScript planner + executor (apps/daemon/src/mcp-agent-install.ts,
runMcpInstall in cli.ts) and its tests are unchanged — they're the
true core for the 10 agents that don't have plugin marketplaces.

## Verified

- JSON validates for all 3 manifests.
- Daemon already serves stdio MCP on `od mcp` (pre-existing,
  /api/mcp/install-info confirms).
- `claude plugin install open-design@nexu-io/open-design` flow: I
  validated the same manifest shape on a sister repo (nexu-xray,
  https://github.com/nexu-io/agent-pr-explore) and it installs cleanly
  on Claude Code + codex from a single marketplace manifest.

## NOT verified yet (worth a smoke on this branch)

- The full `od mcp install <agent>` flow for the 10 non-plugin
  agents (cursor / copilot / cline / opencode / openclaw / antigravity
  / gemini / trae / kimi / hermes-pi-vibe-print-only). The unit tests
  cover plan generation; an end-to-end against a real `claude mcp
  list` / a real cursor.mcp.json would catch shape regressions.

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: lefarcen <ontf116@gmail.com>
2026-06-01 22:15:06 +08:00
071db7ca1b [codex] Stabilize HTML deck navigation state (#3142)
* fix: stabilize html deck navigation state

* fix: avoid misclassifying transform decks as scroll decks

* fix: detect default root-scroller decks

---------

Co-authored-by: Nongzi <3051966228@qq.com>
2026-05-29 07:41:10 +00:00
912c7e380a fix(plugin): infer semantic roles for token maps (#3231)
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
2026-05-29 03:50:56 +00:00
Yuhao ChenandGitHub d0921ed335 fix(skills): avoid orphan web prototype files (#3253) 2026-05-29 03:18:19 +00:00
f8c860a505 feat(landing-page): localize plugins library across 18 locales (#3010)
* feat(landing-page): localize plugins library across 18 locales

PR #2926 shipped the new `/plugins/` library hub + four kind sub-routes
+ detail pages, but the chrome was English-only — visitors landing on
`/zh/plugins/` saw the old marketplace registry placeholder rendered
by the catch-all instead, and detail pages rendered identical English
copy regardless of locale prefix. This PR brings the plugin surface
to feature parity with `/zh/skills/`, `/zh/templates/`, `/zh/systems/`,
`/zh/craft/`.

## What changes

- New `app/_lib/plugins-i18n.ts` — single source for all plugin chrome
  copy (hub, list pages, chip rails, share dialog, detail-page meta
  labels). English baseline + 17 locale overrides keyed on
  `LandingLocaleCode` (the same short-code shape `localeFromPath()`
  returns). Missing keys per locale fall back to English so a
  partially-translated locale still renders sensibly. Translations
  cover hub copy, four tile titles + blurbs, seven artifact-kind
  labels + descriptions, 23 scene-subcategory labels, 18 detail-page
  chrome strings, and a six-key share-dialog table with a
  per-locale `shareTemplate({title, url})` function (translated for
  every locale where `_lib/i18n.ts` already had one — same voice).
- `app/pages/plugins/{,templates/,templates/[kind]/,skills/,systems/,
  craft/,[slug]/}/index.astro` — every hardcoded English string now
  reads `getPluginsCopy(locale)` keys. Page logic and routing
  unchanged.
- New short-code wrappers under `app/pages/[locale]/plugins/` — six
  files (hub + three sub-routes + `[kind]/` and `[slug]/`) following
  the same pattern `[locale]/skills/index.astro` already uses: each
  re-exports the canonical page component and adds a per-locale
  `getStaticPaths()` so the build emits 17 locale prefixes per
  plugin route. Total plugin-route prerender count goes from ~390 to
  ~7 000, matching the existing skill/template scaling.
- Catch-all (`[locale]/[...path].astro`) — old `getPublicPlugins` /
  `getRegistryCounts` registry rendering removed (placeholder UI
  that was never wired to a real marketplace data source). Plugin
  routes now live exclusively under `[locale]/plugins/...` short-code
  wrappers, so the catch-all stops claiming `'plugins'` as a route
  root. The dead-code path also drops a `pluginCounts.all` reference
  the title row was reading.
- `.plugins-tile-grid` styles promoted from a scoped `<style>` in the
  default-locale hub to global `app/sub-pages.css` so the
  short-code wrapper renders the same hub markup without re-mounting
  per-page CSS — `display: contents`-style scoping pitfalls in
  Astro's per-component CSS scoping made this the cleanest fix.

## Surface area

- [ ] **UI** — new page / dialog / panel / menu item / setting / empty state in `apps/web` or `apps/desktop`
- [ ] **Keyboard shortcut** — new or changed
- [ ] **CLI / env var** — new `od` subcommand or flag, new `tools-dev` flag, or new `OD_*` env var
- [ ] **API / contract** — new `/api/*` endpoint, new SSE event, or changed shape in `packages/contracts`
- [ ] **Extension point** — new entry under `skills/`, `design-systems/`, `design-templates/`, or `craft/`, or change to the skills protocol
- [ ] **i18n keys** — new translation keys (full plugin chrome added across all 18 locales)
- [ ] **New top-level dependency** — adding any new entry to the **root** `package.json`
- [ ] **Default behavior change** — changes what existing users experience without opting in
- [x] **None** — landing-page-only restoration of i18n parity for the plugin surface

## Validation

- `pnpm --filter @open-design/landing-page typecheck` → 0 errors
- `pnpm --filter @open-design/landing-page build:static` → 16 127 pages
  built (+6 584 over current main: ~388 plugin detail pages × 17
  locale prefixes plus the hub + four sub-routes × 17 locales).
- `copy-example-html.ts` reports `266 entry files + 65 referenced
  files`, identical to before — no regression in the asset-mirroring
  pipeline.
- Local Playwright smoke (`/zh/plugins/...`):
  - `/zh/plugins/` renders `<title>插件库 · Open Design</title>`,
    label `插件库`, h1 `407 个可组合的构件。`, four tiles labelled
    `模板 / 技能 / 设计系统 / 工艺`.
  - `/zh/plugins/templates/video/` renders h1 `48 视频`, scene chips
    `全部 / 动效 / 短视频 / 营销 / 产品 / 数据讲解`.
  - `/zh/plugins/example-article-magazine/` share dialog renders
    `复制下面的文案、然后跳到你想分享的平台粘贴即可` etc., share
    template auto-interpolates plugin title + URL into Chinese voice.
  - All 18 locale prefixes (`/zh`, `/zh-tw`, `/ja`, `/ko`, `/de`,
    `/fr`, `/ru`, `/es`, `/pt-br`, `/it`, `/vi`, `/pl`, `/id`, `/nl`,
    `/ar`, `/tr`, `/uk`) → 200 across hub + four sub-routes + sample
    detail page.
  - English `/plugins/` unchanged (default-locale path bypasses the
    `[locale]/...` wrapper).

* feat(landing-page): finish plugins i18n chrome across 18 locales

The first localization pass shipped a partial fix: hub headings, lead
copy, two-level page chrome, detail-page metadata labels, the share
dialog, and the chip rail were still falling back to English on every
non-English locale because plugins-i18n.ts only filled a chrome slice
for `zh` and the file header even claimed "7 artifact-kind labels and
25 scene-subcategory labels are translated" for every locale that did
not yet have those blocks.

Three changes close the visible gap:

1. plugins-i18n.ts: fills the 27 still-missing chrome fields per locale
   for zh-tw / ja / ko / de / fr / ru / es / pt-br / it / vi / pl / id /
   nl / ar / tr / uk. Includes the 7-key category map, the 23-key
   subcategory map, hubHeading / hubLead, the 4 *Label / *Heading /
   *Lead triples for the templates / skills / systems / craft hub
   pages, the 4 tile blurbs, the 4 browse buttons, sceneLabel, allChip,
   the 12 detail-page metadata labels (mode / scenario / platform /
   surface / author / manifest id / tags / preview caption / find on
   GitHub / homepage / open in new tab) and bucket label map, the
   detail share dialog (title / copy link / jump-to), and the
   header-side nav.plugins entry. zh receives the same 11 detail-page
   and share-dialog labels it was also missing.

2. header.tsx + site-footer.astro: routes the hardcoded "Plugins /
   Templates / Skills / Systems / Craft" labels through `nav.*` from
   HeaderCopy, so every locale gets its own dropdown trigger and
   footer column. Adds `nav.plugins` to HeaderCopy and fills it in 18
   locales with the local form ("插件" / "プラグイン" / "Plugins" /
   "Plug-ins" / "Plaginy" / "الإضافات" / etc).

3. plugin-row.astro + content-i18n.ts: chip rail. The bundled-plugin
   branch now runs raw `mode` / `scenario` slugs through the shared
   localizeTaxonomyValue, and that helper now also consults the
   plugins-i18n subcategory map before giving up. localizeTaxonomyValue
   now returns undefined on a true miss instead of the unknownTag
   placeholder, so chips drop quietly instead of showing "Category" /
   "分類" / "Categoría" for taxonomy slugs we have not localized yet.
   Callers that genuinely want the placeholder (`localizeContentTag`,
   blog `category`, system noun) still keep the explicit fallback.

Out of scope and tracked separately: per-plugin title and description
in plugins/_official/* (author-supplied English metadata, ~401 plugins
without an i18n schema in the manifest yet — needs RFC + tooling
before the manifests can be expanded), and adding the long tail of
mode / scenario / category slugs (`code-migration`, `plugin-sharing`,
`tune-collab`, `live-artifacts`, `engineering`, ...) to TAXONOMY_TERMS
so chips render localized labels for every taxonomy value rather than
dropping silently.

* feat(landing-page): cover plugins chip rail long-tail taxonomy slugs

PR #3010's first round localized the high-frequency mode/scenario
chips (prototype, video, image, marketing, design, ...) but left the
~37 mode/scenario and 14 category slugs that show up in real `od.*`
metadata — code-migration, plugin-sharing, design-system, planning,
scenario, refine, discovery, handoff, token-map, tune-collab, orbit,
live-artifacts, engineering, healthcare, hr, sales, support,
default-router, downstream-export, figma-migration, media-generation,
plugin-authoring, validation, 3d-shaders, animation-motion,
audio-music, creative-direction, design-systems, diagrams, documents,
image-generation, marketing-creative, screenshots, slides,
video-generation, web-artifacts, ... — falling through to undefined
and dropping their chip silently on every non-English locale.

The data layer is the source of truth here, so this expansion lands
in `content-i18n.ts:TAXONOMY_TERMS` / `CATEGORY_LABELS` rather than
the plugins-i18n catalog: a single dictionary entry per slug fans out
to every chip-rail consumer (catalog rows, detail metadata, the
templates/[kind] facets) without each consumer touching its own copy.

Translations cover all 17 non-`en` locales. Brand and product nouns
(Figma, Open Design, BYOK, plugin) stay literal; technical taxonomy
slugs get short equivalents that read as chips rather than full
prose. The result on `/ja/plugins/skills/` matches `/plugins/skills/`
chip-for-chip (30 chips both sides) instead of dropping 27 of them
the way the previous iteration did.

* feat(landing-page): read manifest title_i18n / description_i18n on bundled plugins

PR #3010's prior rounds localized chrome and chip rails but the
catalog's most prominent text — each row's plugin name and blurb —
stayed English on every non-English locale. The plugin manifest
schema (`packages/contracts/src/plugins/manifest.ts`) has supported
`title_i18n` and `description_i18n` (Record<locale, string>) on every
manifest from spec v1; ~24 of the 401 first-party manifests already
carry one for `zh-CN`. The reader was just never wired to use them.

This change does the reader half: bundled-plugins.ts captures the
two i18n maps off each `open-design.json`, plugin-row.astro and the
detail page resolve them at render time via two new helpers
(`resolveBundledTitle`, `resolveBundledDescription`) that mirror the
short→long fallback chain documented in the manifest spec
(`htmlLang` like `zh-CN` → short `LandingLocaleCode` like `zh` →
primary tag → `en` → English baseline). The static-paths pass still
runs once for all locales — it has to, since each manifest produces
one URL — but the title/description shown on the rendered page now
reads the locale off `Astro.url.pathname` and picks the right entry
out of the maps.

Verified locally: `/zh/plugins/example-card-twitter/` now reads
"Twitter 分享卡 / 推特金句 / 数据卡, 适合配推文" from the manifest's
existing `zh-CN` block instead of the English baseline.

Plugin-data half follows in a separate commit. The 17 non-English
locales × 401 manifests need backfilling so the reader has something
to resolve to; that's data, not schema, and lands as a sequence of
manifest patches rather than tangled with this code change.

* feat(plugins): translate scenarios bucket title/description across 17 locales

Closes the first chunk of #3028. Eleven scenarios plugins (the
default-scenario bundle for each taskKind: code-migration,
figma-migration, media-generation, new-generation, tune-collab,
plugin-authoring; the default design router; the React / Vue /
Next.js downstream-export starters; and the Refine baseline) get
title_i18n + description_i18n filled for all 17 non-English locales
the landing page serves (zh-CN, zh-TW, ja, ko, de, fr, ru, es,
pt-BR, it, vi, pl, id, nl, ar, tr, uk).

The reader landed in 7ddfe36; this commit is data-only. taskKind
slugs that other docs reference by name (`code-migration`,
`figma-migration`, `tune-collab`, etc.) stay literal in the
descriptions so cross-references still resolve. Brand nouns —
Open Design, Next.js, React, Vue, Figma — also stay literal.

`/ja/plugins/od-code-migration/` now reads
"コードマイグレーション(デフォルトシナリオ)" instead of the English
baseline; `/zh/plugins/skills/` shows "代码迁移(默认场景)" in the
catalog row.

Remaining buckets (image-templates 45, video-templates 50,
examples 140, design-systems 142 = 377 plugins) follow in
subsequent commits in this PR.

* fix(landing-page): drop CJK template wrap when source name is still English

The Chinese / Japanese / Korean fallback templates for craft, skill,
template, system, plugin, and blog text splice the source `name` /
`title` into a CJK sentence frame: ``${name}工艺规则``,
``Open Design 指南:${topic}``, ``${name} は…のスキルです``. When the
underlying SKILL.md / craft markdown / blog frontmatter still ships
an English name (true for ~95% of the catalog today), that produces
mid-sentence script straddling on `/zh/...`, `/zh-tw/...`, `/ja/...`,
`/ko/...` like:

  H1   : "Editorial typography hierarchy工艺规则"
  Lead : "这条 Open Design 工艺规则定义 Editorial typography hierarchy
          的执行标准…"
  Plug : "video 插件 · 3D Animated Boy Building Lego"

That reads worse than the all-English fallback, because the visitor
parses the page in two scripts at once.

Adds a `nameNeedsEnglishFallback` guard that fires for the four CJK
locales whenever the spliced-in name has no CJK characters of its
own, and threads it through every `localizeXxxText` helper:
craft, template, system, plugin, skill, blog. When it fires the
helper returns the raw English content untouched, so the section
renders end-to-end in one language. Chrome (header, footer, breadcrumb,
buttons, share dialog) keeps its CJK rendering — only the
title-and-lead block falls back.

Side benefit: the same guard kicks in on the long tail of plugin
manifests still pending `title_i18n` / `description_i18n` backfill
(tracked in #3028), so `/zh/plugins/<bundled>/` no longer pairs a
"video 插件 · 3D Animated Boy Building Lego" title with a Chinese
breadcrumb. The page reads "3D Animated Boy Building Lego" + the
English manifest description, while header / footer / breadcrumbs
stay localized. Once a manifest ships its i18n maps, the chrome and
body re-converge automatically.

Non-CJK non-Latin scripts (ar, vi, ...) keep the previous behavior —
their templates already read tolerably with English names. If that
turns out to be wrong on a real audit, the same guard generalizes by
adding the matching Unicode range and locale set.

* feat(plugins): translate image-templates bucket title/description across 17 locales

44 of 45 image-templates plugins get title_i18n + description_i18n
filled for all 17 non-English locales (zh-CN, zh-TW, ja, ko, de, fr,
ru, es, pt-BR, it, vi, pl, id, nl, ar, tr, uk). Generated via Claude
Sonnet 4.5 over the OpenRouter gateway, ~$1.38 in API spend, 156s
wall-clock. Brand and cultural references stay literal (Open Design,
Lego, Hanfu, Showa, Pokémon, Black Myth: Wukong). Long AI generation
prompts collapse to a 1-2 sentence summary capturing what the plugin
does — the description doubles as catalog blurb on the landing site,
not as the actual generation prompt (which lives in example.html /
the manifest's preview entry).

Skipped: `profile-avatar-realistically-imperfect-ai-selfie` returned
malformed JSON on three retries; will rerun with a tighter prompt in
a follow-up commit. Catalog rows for that plugin keep falling back to
the raw English fields per #3010's reader change, so nothing breaks.

Tracking: closes the image-templates row in #3028.

* feat(plugins): translate video-templates bucket title/description across 17 locales

49 of 50 video-templates plugins get title_i18n + description_i18n
filled for the 17 non-English landing locales. Generated via Claude
Sonnet 4.5 over OpenRouter, ~$1.47 in API spend, 177s wall-clock.
HyperFrames templates, the Three Kingdoms cinematic series, the
Seedance/short-film prompts, and the K-pop / wuxia / anime variants
all get a 1-2 sentence catalog blurb in each locale; brand and
cultural tokens (Black Myth: Wukong, Hanfu, Showa, Pokémon, Three
Kingdoms / 三国志, Lego, Disney, K-pop, HyperFrames) stay literal.

Skipped: `live-action-anime-adaptation-water-vs-thunder-breathing-duel`
returned malformed JSON on three retries; will rerun in followup.
Falls back to the raw English fields per the reader landed in 7ddfe36.

Tracking: closes the video-templates row in #3028.

* feat(plugins): translate examples bucket (117/140) title/description across 17 locales

117 of 140 examples plugins get title_i18n + description_i18n filled
for the 17 non-English landing locales. Generated via Claude Sonnet
4.5 over OpenRouter, $3.94 in API spend, ~13 min wall-clock at
8-way concurrency. Existing zh-CN translations on 24 manifests are
preserved (the merge keeps author-supplied entries and only adds
missing locales).

23 of 140 returned malformed JSON on three retries — the output
likely hit the 4000 max_tokens ceiling on plugins whose description
balloons across 17 locales. Those manifests fall back to English on
non-`en` rendering per the reader landed in 7ddfe36, and will rerun
in a follow-up commit with a larger token budget and a stricter
output schema.

Tracking: closes 117/140 of the examples row in #3028; the remaining
23 stay open in that issue's failure list.

* feat(plugins): translate design-systems bucket (141/142) title/description across 17 locales

141 of 142 design-systems plugins get title_i18n + description_i18n
filled for the 17 non-English landing locales. Generated via Claude
Sonnet 4.5 over OpenRouter, $2.55 in API spend, 301s wall-clock at
8-way concurrency.

Translator script gained two improvements between examples and this
bucket:
- max_tokens bumped from 4000 to 8000 so 17-locale outputs stop
  truncating on the long-tail manifests with verbose descriptions
- a balanced-brace JSON extractor that pulls the outermost `{ ... }`
  from the response, tolerating trailing prose Claude occasionally
  appends after the JSON object.

Result: only 1 manifest (`totality-festival`) failed parse this
batch, down from ~16% on the examples bucket. The next commit
re-runs the prior buckets' failures with the improved script.

Tracking: closes 141/142 of the design-systems row in #3028.

* fix(plugins): backfill 4 plugins that retried green after JSON extractor improvement

dcf-valuation, social-media-dashboard, wireframe-sketch (examples
bucket) and live-action-anime-adaptation-water-vs-thunder-breathing-duel
(video-templates bucket) parse cleanly under the balanced-brace
extractor introduced for the design-systems batch. The remaining
22 failures from the prior runs hit a different parse mode (Claude
emitting unescaped double quotes inside string values when the source
description contains its own English quotes like 'make it professional');
those will need a tighter prompt and rerun.

* fix(plugins): translate the last 22 plugins with quote-handling prompt fix

The 22 stuck plugins all carried English / Chinese double-quoted
phrases inside their description (\"make it professional\",
\"What's inside\", \"电子杂志 × 电子墨水\") that Claude was emitting
back inside JSON string values without escaping, breaking the parse.

Added one rule to the translator prompt — never use a straight double
quote inside a translated string, prefer single quotes / curly quotes
/ CJK 『 』 / 《 》 — and the previously stuck batch sailed through
clean: 22/22 ok, 0 retries, $0.85.

This closes the long tail of #3028:
- scenarios   11/11   ✓
- image-templates 45/45 ✓
- video-templates 50/50 ✓
- examples    140/140  ✓
- design-systems 142/142 ✓
- atoms       N/A (filtered from public catalog)

All 388 catalog-visible plugins now ship title_i18n + description_i18n
for all 17 non-English locales the landing page serves.

* fix(plugins): clean up four review-flagged i18n data issues

- apps/landing-page/app/_lib/plugins-i18n.ts:759 — Polish bucket
  label `examples: 'Przyklad'` was missing the diacritic; every
  other Polish string in the same block uses proper diacritics.
  Restore to 'Przykład'. (Reviewer: looper #4364985878.)

- video-templates/cinematic-route-navigation-guide — German
  title_i18n.de was a byte-for-byte copy of en ("Cinematic Route
  Navigation Guide") while the German description was already
  translated. Replace with "Cinematischer Routen-Navigationsleitfaden"
  to match the German voice the description sets.

- video-templates/hollywood-haute-couture-fantasy-video-prompt —
  Dutch title_i18n.nl was identical to en for the same reason.
  Translate the trailing noun phrase: "Hollywood Haute Couture
  Fantasy Videoprompt" (mirrors the Dutch description's compound
  word style).

- video-templates/video-seedance-three-kingdoms-guanyu-slaying-yanliang —
  Korean Hangul `돌진` had leaked into the Turkish description (a
  translation-pipeline artifact where the model copied the verb
  from the Korean output without translating it). Replace
  "saflarına돌진 eder" with the idiomatic Turkish "saflarına dalar".

All four are data-only fixes against existing manifests; no schema
changes, no reader changes. typecheck stays at 0 errors.

* fix(landing-page): localize aria-labels, alt text and BreadcrumbList JSON-LD on plugin detail page

The PR's prior rounds left six accessibility / structured-data
surfaces on `/{locale}/plugins/<slug>/` either entirely English or
mixing English chrome with the localized plugin title. Reviewer
flagged each one across multiple loops; this commit clears them all:

1. `aria-label` on the open-in-new-tab popout no longer reuses the
   visible label `pcopy.detailOpenInNewTab` (which carries the
   decorative `↗`). Added `detailOpenInNewTabAria` — same wording,
   no glyph — and the `<a aria-label>` consumes that key. The
   visible link text still ends in `↗`.

2. `<nav class="breadcrumb" aria-label="Breadcrumb">` now reads
   `aria-label={pcopy.breadcrumbLabel}`. Eighteen locales filled
   ("面包屑导航", "パンくずリスト", "Brotkrumen-Navigation",
   "Fil d'Ariane", "مسار التنقل", "İçerik haritası", ...).

3. Share-dialog `<button aria-label="Close">` now reads
   `aria-label={pcopy.shareDialogClose}`. Eighteen locales filled
   ("关闭", "閉じる", "Cerrar", "Закрыть", "إغلاق", ...).

4. Three template-literal a11y strings (`${pluginTitle} preview`,
   `Open interactive preview for ${pluginTitle}`, `${pluginTitle}
   interactive preview`) become function calls
   (`pcopy.previewImageAlt(t)`, `previewSummaryAria(t)`,
   `previewIframeTitle(t)`) so the sentence frame around the
   plugin title rotates with the page locale. Two `<img alt>` call
   sites (the static preview at line 210 and the click-to-expand
   thumbnail at line 179) both consume `previewImageAlt`.

5. `BreadcrumbList` JSON-LD position-2 now reads
   `name: pcopy.hubLabel` instead of hardcoded English `"Plugins"`.
   The visible breadcrumb at line 105 already renders
   `pcopy.hubLabel`; this aligns the structured data with the
   rendered chrome on every locale.

The new function-typed keys deliberately interpolate `pluginTitle`
(which is itself locale-resolved via `resolveBundledTitle`) so the
mixed-language guard from commit 002d457 is preserved: a manifest
without a per-locale title still flows through to a coherent
single-language a11y string because `pluginTitle` falls back to
English along with the rest of the section.

apps/landing-page typecheck stays at 0 errors.

Closes reviewer threads:
- #pullrequestreview-4364985878 (Open in new tab aria)
- #pullrequestreview-4368926224 (Polish typo + plus mixed-language alt/aria)
- #4373... (BreadcrumbList JSON-LD)
- #4374... (aria-label="Close" + aria-label="Breadcrumb")

* fix(landing-page): redirect legacy fa/hu/th /plugins/ paths to canonical

When the new `/{locale}/plugins/...` short-code wrappers landed, the
legacy catch-all `pages/[locale]/[...path].astro` dropped `'plugins'`
from its `paths` list. That intentionally avoids serving stale
marketplace-registry placeholder routes for the modern landing
locales — but it also takes `/fa/plugins/`, `/hu/plugins/`, and
`/th/plugins/` from 200 to 404, because those three legacy locales
live only in the old `_lib/i18n.ts:LOCALES` set and are not part of
`LANDING_LOCALES` (the modern 18-locale list the new wrappers serve).

Three `301`s in `_redirects` send those legacy URLs to the canonical
English `/plugins/...` so SEO and inbound links keep working until
the legacy locale set is retired entirely.

Reviewer thread (#pullrequestreview-4364052045) flagged this as a
non-blocking regression across multiple loops; this commit closes it.

* ci(landing-page): add merge_group trigger so the queue can clear PRs

`landing-page-ci.yml` only fired on `pull_request` and `push:main`,
which meant the required `Validate landing page` and
`Strict PR visual tests` checks never dispatched against the
`merge_group` ref the merge queue creates. The queue then sat at
"awaiting checks" until it timed out and ejected the PR (the
deadlock observed during the 5/26 release window).

Adding a `merge_group: { types: [checks_requested] }` trigger to
the same workflow lets the queued ref reuse the existing job graph,
matching the pattern in `ci.yml` which already wires `merge_group`.

Also drops `plugins/**` into the same paths filter as `pull_request`
since the new bundled-plugins reader (commit 7ddfe364) consumes
those manifests' `title_i18n` / `description_i18n` maps and the
landing-page CI must rerun when manifest data changes.

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-27 09:30:59 +00:00
吴杨帆andGitHub 3cac559ccd fix(design-systems): align mission-control success and danger tokens (#3036)
Use DESIGN.md telemetry palette values in tokens.css and the
components.html fixture. Document the --success/--danger mapping in
DESIGN.md so spec readers and CSS consumers stay aligned.
2026-05-27 04:45:10 +00:00
ceb636aa1b feat(landing-page): plugin detail page interactive preview + share dialog (#2958)
* feat(landing-page): plugin detail page interactive preview + share dialog

The new `/plugins/<manifest-id>/` detail page that shipped in #2926
landed without the two affordances PR #2679 added to the legacy
`/skills/<slug>/` and `/templates/<slug>/` pages: a click-to-expand
iframe of the live artifact, and a share dialog with brand-keyword
copy plus four-channel jump buttons (X / LinkedIn / Reddit /
Facebook). This restores both, sourced from the bundled-plugin
manifest under `plugins/_official/<bucket>/<slug>/open-design.json`.

## Interactive preview

Three preview-type behaviours, gated on `od.preview.type`:

  - `video` (Cloudflare Stream URLs already in the manifest) —
    inline `<video controls poster=...>` with the playable MP4 as
    `<source>`. Detail-page row is unchanged from #2926; controls
    double as the open-full affordance.
  - `html` (a local `example.html` referenced by `od.preview.entry`,
    only the `examples/` bucket today) — `<details>` toggle wraps the
    poster image as the summary; clicking opens a sandboxed
    `<iframe>` that loads the entry HTML lazily, with an
    "Open in new tab ↗" pill in the frame's top-right corner so the
    artifact can be inspected at full screen.
  - `image` or no entry — static `<img>` (existing behaviour).

`copy-example-html.ts` is extended to mirror the local entry and any
`./assets/...` siblings to `out/plugins/<manifest-id>/<entry>` so the
iframe URL resolves on Cloudflare Pages instead of SPA-falling-back to
the homepage. The four examples carrying sibling-asset references
(flowai-live-dashboard-template, trading-analysis-dashboard-template,
open-design-landing, open-design-landing-deck) all render in-place.

## Share dialog

Same `<dialog data-share-dialog>` markup the legacy detail pages use,
so the global click handlers in `header-enhancer.astro`
(`data-share-open` / `data-share-copy` / `data-copy-link`) wire up
the open / copy actions automatically — no extra client bundle. Four
platform jumps (X / LinkedIn / Reddit / Facebook) plus a Copy-text /
Copy-link pair, with a single English template for now (the new
`/plugins/...` routes only generate English pages; localisation can
land alongside the i18n catch-all follow-up).

## Bundled in

- The `copy-example-html.ts` sibling-assets fix from open PR #2880.
  Without it the existing `/skills/<slug>/` iframe still 404s on
  Cloudflare Pages for after-hours-editorial-template and the four
  others; bundling it here means the same script handles both
  sources in one pass and sidesteps two PRs touching identical
  helper code.

* fix(plugins): remove dangling preview.entry from example-hyperframes

The hyperframes example folder ships a SKILL.md (it's an instruction
manual for using the HyperFrames HTML format) but no runnable
`example.html`. The manifest still claimed `preview.type: html` /
`preview.entry: ./example.html`, which made the marketing site try
to iframe a non-existent file and forced the preview pipeline into
its `Path 3` fallback card — leaving the catalog row visually
inconsistent with the eleven sibling `video-template-hyperframes-*`
plugins that have real Cloudflare-Stream poster URLs.

Drop the preview block entirely so the manifest stops promising a
demo it can't deliver. The landing-page detail row continues to
render the typographic fallback card (sourced from title /
description / mode), which is now the honest representation:
"this is an instruction skill, not a renderable template".

* fix(landing-page): address PR #2958 review feedback on plugin preview pipeline

Two blocking issues called out in code review:

1) `bundled-plugins.ts` exposed `previewEntryUrl` for every manifest
   that declared `preview.type: "html"`, even when the entry file
   wasn't shipped. Several first-party manifests fall in this state
   (example-design-brief's `./brief-preview.html`, example-x-research,
   example-pptx-html-fidelity-audit, example-hatch-pet,
   example-last30days, example-guizang-ppt, example-replit-deck,
   example-live-artifact, example-html-ppt, example-dcf-valuation).
   The detail page then rendered a click-to-expand iframe and popout
   link to a file that copy-example-html.ts had skipped, so the
   iframe URL SPA-fell-back to the homepage on Cloudflare Pages.

   `entryRelativeUrl()` now `existsSync()`-checks the resolved local
   path before returning a URL. When the file's missing the detail
   page falls through to the static thumbnail branch, exactly like
   plugins that ship no preview entry at all.

2) `copy-example-html.ts` recognised only `(src|href|poster)="./assets/..."`
   and then bulk-copied the entry's sibling `assets/` folder, so it
   missed two real ref shapes: bare-relative (`href="assets/styles.css"`,
   `src="assets/deck-stage.js"` under example-html-ppt-zhangzara-pin-and-paper)
   and cross-folder (`src="../open-design-landing/assets/hero.png"`
   under example-open-design-landing-deck).

   Replaced the heuristic with a generic walker that:
   - Parses every relative ref in the entry HTML
     (`(src|href|poster|srcset|data-src)=` plus `url(...)`), splitting
     srcset on whitespace/commas so multi-URL attrs are honoured.
   - Resolves each ref against `dirname(entrypointSrc)` for the source
     and against `dirname(iframeAbsPath)` for the destination —
     identical to how a browser resolves the same ref against the
     iframe URL. Files outside the source root or the iframe root
     are dropped.
   - Recurses into copied HTML / CSS / JS / SVG so multi-step chains
     (entry → assets/template.html → assets/fonts/foo.woff) don't
     strand intermediate files.
   - Tracks visited *destinations* rather than sources, so a single
     source that legitimately needs to land at two different out-paths
     (same-folder copy at /plugins/example-X/assets/foo.png AND a
     cross-folder copy at /plugins/open-design-landing/assets/foo.png
     for sibling decks that use `../open-design-landing/assets/foo.png`)
     gets both copies.

Verified manually:
- /plugins/example-html-ppt-zhangzara-pin-and-paper/assets/styles.css
  and assets/deck-stage.js → 200 (bare-relative)
- /plugins/open-design-landing/assets/hero.png and assets/about.png
  → 200 (cross-folder destination, no manifest-id prefix because
  iframe URL `..` collapses the prefix)
- /plugins/example-design-brief/ renders the static thumbnail only,
  no click-to-expand iframe (broken entry guard)
- /plugins/example-flowai-live-dashboard-template/assets/template.html
  → 200 (existing same-folder behaviour preserved)

Build now reports `copied 266 entry files + 65 referenced files`,
where the 65 includes both the same-folder `./assets/...` payloads
the previous heuristic captured and the bare-relative + cross-folder
shapes it didn't.

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-26 07:43:46 +00:00
587f6de46d fix: restore Atelier Zero deck plugin prompt (#2822)
Co-authored-by: icc <iccccccccccccc@users.noreply.github.com>
2026-05-24 14:20:25 +00:00
lefarcen c14baf07d3 Merge origin/main into release/v0.8.0
PR #2461 sync prep — resolves 14 conflicts merging 84 main-side commits
on top of 58 release-side commits accumulated during the 0.8.0 cycle.

Resolution summary:

Take main (theirs) where main carried deliberate forward progress:
- apps/web/src/components/PluginCard.tsx — 7 hunks, i18n migration:
  hardcoded English aria-labels/titles replaced with t() calls keyed
  on pluginCard.* (all 8 keys verified present in en.ts).
- apps/web/src/components/TasksView.tsx — 1 hunk, source-ingestion
  feature: sortedRoutines (newest-first), sourceIngestionTemplates,
  patchSourceForm, submitSourceIngestion. activeCount/pausedCount
  semantics preserved (now keyed on sortedRoutines, count unchanged).
- e2e/ui/app.test.ts — new node:fs/promises + tmpdir + path + @/timeouts
  imports needed by main-side test helpers.
- e2e/ui/settings-local-cli-codex-fallback.test.ts — menu-dismissal
  helper block added by main.

Keep both sides where each added a different field to the same object
literal:
- apps/web/src/components/ProjectView.tsx (locale + analyticsHints
  spread).
- apps/web/src/components/DesignSystemFlow.tsx (locale + analyticsHints).

Take release (ours) where release carried deliberate work that ships
0.8.0:
- CHANGELOG.md — release-side 0.8.0 entry + PR link refs; main's
  Unreleased section was the same body of work, now finalized.
- apps/landing-page/public/{apple-touch-icon,favicon}.png +
  apps/web/public/app-icon.svg — release-side visual refresh assets
  consistent with 0.8.0 stable ship.
- tools/pack/src/linux.ts — packageVersion const required by line 466;
  taking main's empty line would build-error.
- e2e/ui/project-management-flows.test.ts +
  e2e/ui/settings-api-protocol.test.ts +
  e2e/ui/settings-memory-routines.test.ts — release-side release-smoke
  hardening (shangxinyu1 + PerishFire) takes precedence on overlap.

Closes-issue / unblocks: PR #2461 sync release/v0.8.0 → main.
2026-05-23 12:17:18 +08:00
Marc ChanandGitHub a5b47c5f76 fix(ci): narrow workflow scope and reuse setup steps (#2708)
* fix(ci): narrow workflow scope and reuse setup steps

* fix(ci): narrow workflow scope and reuse setup steps

Repair Nix fixed-output hashes for the filtered daemon and web source trees.

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* fix(ci): narrow workflow scope and reuse setup steps

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* fix(ci): narrow workflow scope and reuse setup steps

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)

* fix(ci): repair daemon and nix checks

Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
2026-05-22 18:58:53 +08:00
10e11531a1 Improve deck home previews and plugin gallery performance (#2698)
Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-05-22 17:47:28 +08:00
Siri-RayandGitHub e6da01e998 Add i18n metadata for official content (#2692) 2026-05-22 16:39:32 +08:00
0ba88a064d Add Codex interactive capability map example (#2657)
* Add Codex interactive capability map example

* Fix Codex map preview entry

---------

Co-authored-by: tuolaji <tuola@tuolajideMacBook-Air.local>
2026-05-22 15:49:16 +08:00
Yuhao ChenandGitHub bddec2391d Fix Simple Deck discovery form contract (#2602) 2026-05-22 14:05:24 +08:00
qiongyu1999 48f3404051 fix home example prompt presets 2026-05-21 17:25:09 +08:00
ce95266586 [codex] Polish home composer working-directory controls (#2468)
* Polish design system home flows

* Polish home prompt presets

* Polish home working directory controls

* test: align home hero chrome smoke

* fix: stabilize home composer ci checks

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-05-21 00:22:46 +08:00
lefarcenandGitHub c80acfefeb fix(daemon,web): block pitch-deck placeholder publishes and unbreak framework decks (#2384)
Two preview-time bugs surfaced ahead of 0.8.0:

1. Pitch-deck example (#2215): the official html-ppt-pitch-deck prompt asked
   the agent to confirm three facts first, but the manifest had no
   structured `od.inputs`, so the platform's required-input gate had no
   fields to enforce and the run could publish HTML that still contained
   unresolved fundraising placeholders (`Name to confirm`, `$X.XM`,
   `Replace this panel with`, ...). Add structured required inputs to the
   manifest and a daemon-side publication guard that rejects HTML/deck
   artifact writes whose body still contains those placeholders. Scope is
   the file-write boundary only (no assistant-text scanning), so the
   guard cannot trip on the agent's chat prose mid-clarification.

2. Framework deck preview off-screen: `injectDeckBridge` injected
   `place-content: center !important` on `.deck-shell` for every deck-mode
   srcdoc, which forced the framework's `display: grid` shell to re-center
   its implicit track. The framework's `fit()` already centers a
   `transform-origin: top left` stage with an explicit `translate(tx, ty)`
   that assumes the stage's natural layout position is (0, 0); the two
   centerings stacked and the scaled stage landed ~1000px off-screen, so
   the preview showed a sliver of slide content in the top-left with the
   rest black. Skip the override when the framework's `id="deck-stage"`
   marker is in the doc, and drop the dead `display: grid; place-items:
   center` from the deck framework template so future drift can't
   re-introduce the same stack.
2026-05-20 16:20:34 +08:00
Joey-nexuandGitHub f1870cbf3d chore(featured): curate Featured picks down to top 10 across categories (#1966)
* chore(featured): curate Featured picks down to top 10 across categories

The picker's Featured chip currently surfaces 64 plugins because
`isFeaturedPlugin` (apps/web/src/components/plugins-home/facets.ts)
treats any finite `od.featured` number as featured, and the field
had been adopted incrementally by 51 skills + 13 templates without
a curation step. The result is a "Featured" tab that's effectively
"everything tagged at all" — no editorial signal.

Curate down to 10 picks, allocated to keep the showcase legible:

  0.001  skills/deck-swiss-international
  0.01   skills/deck-guizang-editorial
  0.02   design-templates/magazine-poster              [add]
  0.04   skills/doc-kami-parchment
  0.10   design-templates/web-prototype-taste-brutalist [add od: block]
  0.13   skills/video-hyperframes
  0.14   skills/frame-glitch-title
  0.15   skills/vfx-text-cursor
  0.16   skills/frame-logo-outro
  0.17   skills/deck-open-slide-canvas

Selection mirrors the html-anything `recommended: 1..10` ranking
(html-anything is the upstream content source for these skills, per
the `od.upstream` field on each SKILL.md). Two of those 10 picks
weren't in the prior featured set at all — `magazine-poster` had no
`od.featured` field and `web-prototype-taste-brutalist` had no `od:`
block at all — so they get added rather than just rebalanced.

Removes `od.featured` from the other 56 files. No UI code change;
the existing `isFeaturedPlugin` logic now reads a curated set
instead of an accidental one.

* chore(featured): align baked plugin manifests with curated top 10

The picker reads `od.featured` from each plugin's
`plugins/_official/examples/<id>/open-design.json` manifest, not from
the SKILL.md frontmatter the previous commit edited. Without this
follow-up the curated set of 10 would be invisible to users — the
picker's Featured chip would still surface 27 baked plugins from the
pre-existing manifests.

Mirror the SKILL.md curation into the baked layer:

  removed `od.featured` from 19 manifests:
    article-magazine, card-xiaohongshu, data-report,
    frame-data-chart-nyt, frame-flowchart-sticky,
    frame-light-leak-cinema, frame-liquid-bg-hero,
    frame-macos-notification, guizang-ppt, html-ppt,
    kami-deck, kami-landing, mockup-device-3d,
    open-design-landing-deck, ppt-keynote, resume-modern,
    social-reddit-card, social-spotify-card, social-x-post-card

  added `od.featured` to 2 manifests:
    magazine-poster -> 0.02
    web-prototype-taste-brutalist -> 0.10

Verified locally against `daemon /api/plugins`: featured count is
now exactly 10, matching the SKILL.md source of truth from the
previous commit.
2026-05-18 12:56:26 +08:00
Tom HuangandGitHub 76defffb93 Garnet hemisphere (#1702)
* feat(chat-composer): enhance mention handling and input overlay

- Introduced a new overlay for inline mentions in the chat composer, improving user experience by visually indicating mentions as users type.
- Updated the `ChatComposer` component to manage mention entities and integrate them into the input field, allowing for better context and interaction.
- Enhanced the `AssistantMessage` component to support the display of plugin action panels based on the current project context, facilitating easier plugin management.
- Refactored related components to ensure consistent handling of project files and mentions across the application.

This update significantly improves the chat interaction model, making it more intuitive for users to engage with mentions and plugins.

* feat(plugin-management): enhance plugin action panels and UI components

- Updated the `AssistantMessage` component to include plugin action panels based on the latest project context, improving user interaction with generated plugins.
- Refactored the `PluginsView` to support detailed views for available marketplace entries, allowing users to access more information and actions for each plugin.
- Introduced new CSS styles for improved visual representation of plugin-related UI elements, enhancing overall user experience.
- Enhanced the `listPlugins` function to include an option for fetching hidden plugins, providing more flexibility in plugin management.

This update significantly improves the usability and functionality of the plugin management system, making it easier for users to interact with and manage their plugins.

* fix(assistant-message): refine plugin folder candidate selection logic

- Updated the `pluginFoldersTouchedThisTurn` function to improve the logic for selecting plugin folder candidates based on touched paths and message content.
- Introduced a new helper function, `pathMatchesFolderFileBasename`, to enhance the matching criteria for folder candidates.
- Added a check for explicit folder matches before falling back to a single candidate, improving accuracy in folder selection.
- Modified the `shouldRenderSlotAsText` function in `HomeHero` to include the name parameter, refining the rendering logic for slot text.

These changes enhance the functionality and reliability of the assistant message component in managing plugin folder candidates.

* feat(plugin-folder-actions): implement agent-routed CLI actions for plugin management

- Introduced a new `PluginFolderAgentAction` type to streamline actions related to plugin folders, including install, publish, and contribute.
- Updated the `DesignFilesPanel`, `FileWorkspace`, and `AssistantMessage` components to utilize the new agent action handling, improving user interaction with generated plugins.
- Refactored the action handling logic to send commands to the agent, enhancing the workflow for managing plugin folders.
- Added corresponding tests to ensure the new functionality works as expected and integrates seamlessly with existing components.

This update significantly enhances the plugin management experience by routing actions through the agent, allowing for a more cohesive and interactive user experience.

* Fix PR 1702 CI blockers

* Fix PR 1702 remaining CI checks

* Prebuild AGUI adapter after install

* Restore plugin project snapshot wiring

* feat(marketplace): refactor marketplace URL handling and enhance fetching logic

- Introduced new functions to normalize marketplace URLs and manage fetching of marketplace manifests, improving the reliability of marketplace integrations.
- Updated the server and plugin logic to utilize the new fetching mechanisms, ensuring consistent handling of marketplace data.
- Enhanced tests to cover new URL normalization and fetching scenarios, ensuring robustness in marketplace management.

This update significantly improves the marketplace experience by streamlining URL handling and enhancing data fetching capabilities.

* Fix project auto-send cleanup spec
2026-05-14 21:12:50 +08:00
pftom 9ea33e076b feat(context-plugins): add support for context plugins in project metadata and UI
- Introduced a new `contextPlugins` field in the `ProjectMetadata` type to accommodate plugins selected via `@` mentions, allowing for additive context in project creation.
- Updated the `HomeHero` and `EntryShell` components to handle and display context plugins, enhancing user interaction with selected plugins.
- Implemented rendering logic for context plugins in the metadata block, providing clear visibility of selected plugins and their descriptions.
- Enhanced the UI to support the removal of context plugins and display additional details on hover, improving the overall user experience.

This update significantly enriches the project creation process by allowing users to incorporate multiple context plugins seamlessly.
2026-05-14 15:29:49 +08:00
pftom 3b167b6921 feat(plugins): add registry protocol and enhance plugin management features
- Introduced the `@open-design/registry-protocol` package, enabling improved interactions with plugin registries.
- Updated the `typecheck` script in the daemon's `package.json` to include the new registry protocol.
- Enhanced the CLI with new flags and commands for better plugin management, including `yank` and additional marketplace functionalities.
- Implemented a plugin lockfile system to manage installed plugins and their versions, improving reliability during upgrades.
- Added new marketplace doctor functionality to validate plugin entries and ensure compliance with registry standards.

This update significantly enhances the plugin ecosystem by providing robust registry interactions and improved management capabilities.
2026-05-14 08:55:36 +08:00
pftom 56c264c9bd feat(plugins): add login and whoami commands for GitHub CLI authentication
- Introduced `login` and `whoami` commands to the plugin CLI, enabling users to authenticate with the Open Design registry via GitHub CLI.
- The `login` command wraps GitHub CLI authentication, allowing users to specify a host, defaulting to GitHub.
- The `whoami` command retrieves and displays the authenticated GitHub account information, with an option for JSON output.
- Updated the CLI help documentation to include usage instructions for the new commands.
- Enhanced error handling for GitHub CLI dependencies and authentication status.

This update improves the user experience by simplifying the authentication process for plugin publishing.
2026-05-14 07:25:05 +08:00
pftom 0edbf38171 feat(plugins): add specVersion and version fields to plugin and marketplace schemas
- Introduced `specVersion` and `version` fields to the plugin and marketplace schemas, ensuring better versioning and compatibility tracking.
- Updated various components and functions to handle the new fields, including database migrations, plugin snapshots, and marketplace management.
- Enhanced tests to validate the presence and correctness of the new fields in plugin manifests and marketplace entries.
- Improved documentation to reflect the changes in schema requirements and provide guidance on the new versioning system.

This update strengthens the plugin ecosystem by providing clear versioning, enhancing the reliability and maintainability of plugins and marketplaces.
2026-05-13 22:24:50 +08:00
pftom fbcbd4a643 feat(plugins): add registry publishing strategies and documentation
- Introduced `PUBLISHING-REGISTRIES.md` and its Chinese counterpart, detailing strategies for publishing plugins to skills.sh, ClawHub, and GitHub.
- Updated existing documentation to reference the new publishing guidelines, ensuring clarity on the process for external registry distribution.
- Enhanced `AGENT-DEVELOPMENT.md` and `CONTRIBUTING.md` to include notes on registry publishing, improving the overall authoring experience for plugin developers.

This update provides comprehensive guidance for plugin authors on how to effectively publish their work across various registries, enhancing the accessibility and usability of the plugin ecosystem.
2026-05-13 21:28:16 +08:00
pftom a0a3ad1299 feat(plugins): introduce portable plugin specification and authoring kit
- Replaced the `community/` directory with `spec/`, which now serves as the portable plugin specification and authoring kit, including documentation, templates, and examples for contributors.
- Added new files for agent development, contributing guidelines, and a comprehensive README for the plugin spec kit.
- Updated existing documentation to reflect the new structure and clarify authoring rules for plugins.
- Introduced multiple example plugins under the new `spec/examples/` directory, showcasing various use cases and workflows for plugin authors.

This update enhances the clarity and accessibility of the plugin development process, providing a robust framework for contributors and external agents.
2026-05-13 21:24:36 +08:00
pftom d3d95121f3 feat(plugins): enhance visual score sorting and add new example templates
- Updated the `sortByVisualAppeal` function to prioritize featured ranks, ensuring that curated plugins are displayed prominently.
- Added tests to verify the new sorting logic, ensuring that plugins with numeric featured ranks are sorted correctly ahead of others.
- Introduced new example templates for a magazine article layout, a Twitter share card, and a Xiaohongshu card, expanding the available options for users.
- Enhanced the overall plugin preview experience by integrating these new templates, providing users with more visually appealing and functional examples.

This update significantly improves the plugin sorting mechanism and enriches the template offerings, enhancing user engagement and experience.
2026-05-13 21:02:05 +08:00
pftom 8b2d48a258 feat(daemon, web): enhance plugin preview handling and add new templates
- Introduced logic to assemble example slides with a companion template when the declared entry is missing, improving the user experience for plugin previews.
- Updated the server logic to handle special cases for `example-slides.html`, ensuring proper fallback to `template.html` when applicable.
- Enhanced tests to verify the new preview assembly functionality and ensure correct rendering of fallback content.
- Added new HTML and Markdown examples for various skills, including a magazine article layout and a Twitter share card, expanding the available templates for users.

This update significantly improves the plugin preview experience, providing users with more robust and visually appealing fallback options.
2026-05-13 20:58:24 +08:00
pftom 9e196d34af feat(daemon, web): enhance plugin sharing workflows and UI components
- Updated the plugin sharing prompts to utilize local daemon endpoints for publishing to GitHub and contributing to Open Design, streamlining the user experience.
- Refactored the `PluginsView` and `PluginShareMenu` components to support new sharing functionalities, including confirmation modals and improved link handling.
- Enhanced the CSS styles for the plugin share confirmation modal and related UI elements for better visual consistency.
- Added tests to verify the functionality of the new sharing workflows and ensure proper integration within the existing plugin management system.

This update significantly improves the plugin sharing experience, making it easier for users to publish and contribute their plugins effectively.
2026-05-13 14:35:09 +08:00
pftom c9cc3b88c0 feat(web): standardize plugin terminology and enhance UI components
- Updated terminology from "Community" to "Official" across various components to reflect first-party plugin status.
- Enhanced the ChatComposer, HomeHero, and PluginsHomeSection components to improve user experience and clarity in plugin management.
- Improved CSS styles for better visual consistency and layout across plugin-related interfaces.
- Added tests to ensure proper functionality and visibility of official plugins in the UI.

This update reinforces the distinction between official and user-installed plugins, enhancing the overall user experience in plugin interactions.
2026-05-13 12:19:29 +08:00
pftom c36609c47d feat(daemon, web): implement plugin sharing project creation and enhance CLI functionality
- Added new flags for conversation, message, agent, and model in the CLI to support enhanced plugin sharing features.
- Introduced a new API endpoint for creating share projects for plugins, allowing users to publish to GitHub or contribute to Open Design.
- Updated the UI components to facilitate the new sharing functionalities, including prompts for user input during the sharing process.
- Enhanced the project management system to handle new plugin share actions, improving user interaction and experience.
- Added tests to ensure the reliability of the new sharing features and their integration within the existing plugin management system.

This update significantly enhances the plugin ecosystem by enabling users to share their creations more effectively and streamline collaboration.
2026-05-13 07:01:12 +08:00