* add waitlist-page skill
* fix(waitlist-page): address PR review feedback
- Remove novalidate from example.html form
- Ensure checkValidity() guard present in both template and example
- Remove required from firstname input in template
- Add token escaping rules to SKILL.md workflow (step 9)
- Add token mapping/fallback rules for BORDER/SUCCESS/STRIPE/DECO (step 7)
- Fix mobile quality gate to be measurable (375x667, 390x844)
- Promote hardcoded #fff, rgba(0,0,0,0.9), rgba(255,255,255,0.9) to
CSS variables (--btn-label, --ticker-bg, --ticker-fg) in template
- Create references/checklist.md with P0/P1/P2 tiers; countdown timer
is now a hard P0 prohibition; a11y gate split into six specific checks"
* fix: resolve P0 color and accessibility issues
- Add role=status to success messages for screen reader announcement
- Replace all hardcoded hex/rgba colors with template tokens
- Update SKILL.md with comprehensive color token mapping rules
- SVG decorations now use CSS variables instead of hardcoded strokes
* fix: address PR review feedback on scope, scrolling, and font tokens
Fixes:
- Restore pricing-page files accidentally deleted in previous commit
(skills/pricing-page/SKILL.md and example.html now back on branch)
- Remove temp-original.html scratch file from commit
- Fix mobile viewport scrolling: change 'height: 100vh; overflow: hidden'
to 'min-height: 100svh; overflow-x: hidden; overflow-y: auto'
so content doesn't clip on 375×667 and 390×844 screens
- Split font tokens into URL-safe and CSS-safe variants:
* {{DISPLAY_FONT_URL}} and {{DISPLAY_FONT_CSS}} for display fonts
* {{BODY_FONT_URL}} and {{BODY_FONT_CSS}} for body fonts
This fixes encoding: spaces as '+' in Google Fonts URL, literal in CSS
- Update SKILL.md frontmatter with new font input fields
- Update token escaping rules to document the split
* fix: resolve token contract mismatch and remove hardcoded colors from example.html
P0 Fixes:
- Remove all hardcoded colors from example.html (except #2D6A4F for --success)
- Use CSS variables for all color values: --btn-label, --ticker-bg, --ticker-fg, --deco-stroke
- Fix gradient to use var(--deco) instead of hardcoded #D1632B
- Apply consistent color expressions across decorations and text
Token Contract Fixes:
- template.html now uses full CSS expressions for opacity-based colors:
* {{BORDER_EXPRESSION}} instead of {{BORDER_HEX}} (no # prefix)
* {{BTN_LABEL_EXPRESSION}} instead of {{BTN_LABEL_HEX}}
* {{TICKER_BG_EXPRESSION}}, {{TICKER_FG_EXPRESSION}}, {{DECO_STROKE_EXPRESSION}}
- Remove extra quotes from font tokens in template:
* --font-body: {{BODY_FONT_CSS}} instead of '{{BODY_FONT_CSS}}'
* Font tokens are already quoted if needed, no wrapping
- Update SKILL.md frontmatter with all color expression inputs and descriptions
- Update token mapping rules to clarify the new contract:
* Hex tokens: simple six-digit colors
* Expression tokens: full CSS values (rgba/color-mix), no # prefix
* Font tokens: CSS font-family values, no extra wrapping
- Update token escaping rules to reflect new contract
This ensures agents can follow SKILL.md instructions without producing invalid CSS.
* fix: remove final hardcoded colors from example.html - P0 complete
- Button text: #fff → var(--btn-label)
- Ticker background: rgba(0,0,0,0.9) → var(--ticker-bg)
- Ticker text: rgba(255,255,255,0.9) → var(--ticker-fg)
- Logo text: fill=white → fill=var(--btn-label)
All colors now derive from design system tokens. Only #2D6A4F (--success) allowed hardcoded exception.
* fix: correct --btn-label contrast for CTA readability
Change --btn-label from #1A1410 (same as button background) to #FDE8DF
(light background color) so button text has proper contrast against
the dark --accent button background.
This resolves the black-text-on-black issue that broke the main
email capture action and satisfies the checklist button contrast gate.
* fix: add visible focus indicator for input accessibility
P1 Accessibility Polish:
- Update .form-row input:focus to include outline and outline-offset
- Before: border-color only, removing default outline (no visible focus)
- After: border-color + 2px outline + 2px offset (clear focus indicator)
This satisfies the checklist P1 focus-style gate and ensures keyboard
users can see which form field has focus. Both example.html and
template.html updated so agents copy complete focus patterns.
* fix: remove hardcoded logo shadow color - P0 compliance
- Add --logo-shadow CSS variable derived from foreground
- example.html: box-shadow 0 2px 8px rgba(0,0,0,0.08) → var(--logo-shadow)
- template.html: add {{LOGO_SHADOW_EXPRESSION}} placeholder
- Update SKILL.md with logo_shadow_expression input and mapping rules
All colors in example.html now derive from design system tokens.
Ensures agents copy compliant reference without hardcoded shadow colors.
* fix: register waitlist-page skill in i18n localized content registry
Add waitlist-page to locale-specific skill fallback lists so the web
content coverage test passes when the new skill is discovered:
- apps/web/src/i18n/content.ts: Add to DE_SKILL_IDS_WITH_EN_FALLBACK
- apps/web/src/i18n/content.fr.ts: Add to FR_SKILL_IDS_WITH_EN_FALLBACK
- apps/web/src/i18n/content.ru.ts: Add to RU_SKILL_IDS_WITH_EN_FALLBACK
The skill falls back to English localization for now; localized
descriptions can be added to each locale file later.
Fixes: web content coverage test now passes (6/6 tests).
* fix: wire template and checklist into skill workflow as mandatory gates
Restructure waitlist-page SKILL.md workflow to enforce the hardened
template-based execution path:
- Add Preflight section: agents MUST read assets/template.html first
- Add explicit token mapping and escaping rules (steps 2-4)
- Add mandatory Validation section: run references/checklist.md P0/P1
gates BEFORE emitting artifact; fail fast if any P0 gate fails
- Update Quality gates section to emphasize template-based execution
and reinforce P0/P1 gate hierarchy
- Update Output section: only emit after P0 passes; re-validate on
iterations
This prevents agents from writing HTML from scratch or skipping the
hardened seed (template) and validation (checklist) that this PR adds.
* refactor(waitlist-page): replace literal logo placeholder with token
- Replaced `[LOGO]` with `{{LOGO_MARK}}` in template.html
- Added `logo_mark` to inputs in SKILL.md
- Updated mapping rules in SKILL.md to handle raw SVG or text for logo
- Updated P0 validation gates in SKILL.md and checklist.md to ensure logo replacement
* fix(waitlist-page): enforce strict escaping and sanitization for logo token
- Mandate HTML-escaping for text initials.
- Enforce strict allowlist-based sanitization for inline SVG (stripping `<script>`, `on*`, `<foreignObject>`, `href`, `xlink:href`, `url()`).
- Add fallback to escaped text initials for invalid/unsafe SVG.
* docs(waitlist-page): sync logo_mark frontmatter description with rules
- Updated the `logo_mark` input description in the SKILL.md frontmatter to explicitly outline the new requirements for HTML-escaped text or strict allowlist-sanitized SVG.
* fix(waitlist-page): add logo_fg_expression to guarantee contrast in logo mark text fallback
- Added `--logo-fg` CSS variable mapped to `{{LOGO_FG_EXPRESSION}}`.
- Updated `.logo-container` in `template.html` to inherit typography styles and apply `--logo-fg` for safe fallback when rendering escaped initials.
- Enforced WCAG AA contrast for logo initials against container background in `checklist.md`.
* refactor(waitlist-page): migrate hex color tokens to full css expressions
* refactor(waitlist-page): strict validation for color expression tokens to prevent CSS injection
* docs(waitlist-page): update validation summary to reflect strict color grammar
---------
Co-authored-by: Siri-Ray <2667192167@qq.com>
* Optimize Windows packaged web output
* Fix packaged contracts runtime build
* Optimize Windows packaged size pruning
* Prune Windows root Next payload
* Remove Windows bundled Node runtime
* Prune Windows standalone duplicate Next
* Add tools-pack cache foundation
* Cache Windows packaged build layers
* Cache Windows workspace builds
* Cache Electron-ready Windows app
* Split Windows tools-pack module
* Cache Windows dir build outputs
* Split Windows pack build modules
* Document Windows NSIS smoke namespace limits
* Move Windows NSIS smoke note to agents guide
* Optimize Windows beta packaging
* Bump packaged beta base version
* Improve Windows installer namespace UX
* Improve Windows tools-pack cache keys
* Stabilize Windows beta cache version keys
* Cache Windows workspace build outputs
* Optimize windows release beta cache layers
* Cache windows release dependencies
* Trim windows release cache before save
* Refresh windows tools-pack cache key
* Improve windows installer preflight prompts
* Fallback NSIS installer strings to English
* Fix Windows installer cleanup and preflight
* Improve Windows NSIS state logging
* Fix system NSIS Persian language alias
* Use long-path removal for Windows uninstall
* Fix mac tools-pack tests on Windows
* Address Windows packaging review feedback
* Fix Windows installer cache namespace isolation
* Include web output mode in Windows tarball cache key
* Use unique Windows release cache save keys
* Support overriding the Codex executable path
* Replace save-as-template prompts with an in-app dialog
* Seed local packaged app config from workspace
* Fix packaged config and connection test overrides
* Keep tools-pack mac config seeding self-contained
* Require absolute CODEX_BIN overrides
* docs(readme): add @nexudotio X link + Stay in the loop section
- Add X/Twitter follow badge in the header next to Discord, so visitors
can subscribe to release notes and milestone threads in one click.
- Add a short "Stay in the loop" section above "Star us" pointing to
@nexudotio on X. Discord is for chat, X is for the public milestones
(releases, new skills, new design systems).
No other changes.
* feat(web): add Follow @nexudotio pill to entry sidebar foot
- Surface the official X account next to the Settings/Pet/Language pills
so users can subscribe to release notes from inside the app, not only
the README.
- Uses the existing .foot-pill style (already supports <a>, has
text-decoration: none) and the existing 'external-link' Icon — no new
CSS, no new icons, no i18n key required (single short English label).
- Opens in a new tab with rel="noreferrer noopener".
Pairs with the README badge added in this same PR.
---------
Co-authored-by: Tuola-waj <ge@nexu.io>
* feat(settings): add connection test for providers and CLI agents
Adds a "Test" action in the Settings dialog that verifies the configured
provider (Anthropic/OpenAI/Azure/Google) or CLI agent without sending a
real chat. Backed by a new daemon endpoint and shared contracts, with
categorized inline statuses and i18n strings across all supported locales.
* fix(settings): address connection test review feedback
* fix(daemon): pass empty MCP servers for connection probes
* fix(connection-test): address review blockers
* fix(daemon): fail json stream runs on structured errors
* fix(contracts): build connection test subpath export
* Use draft CLI env in agent connection tests
* fix(i18n): add fallback ids for new curated content
* fix(web): add hover tooltips to Design Files action buttons (#283)
The batch-download, select-all, and clear-selection buttons in
DesignFilesPanel had no title attribute, so users hovering them saw no
tooltip. The other action buttons (refresh, new sketch, paste, upload)
already had titles. Added titles to the three missing ones using the
existing translation keys, so hover behavior is consistent across the
panel.
Closes#283.
* docs: point pi-ai links to pi-mono packages (#275)
The pi project moved from a standalone repo to the pi-mono monorepo.
The old URL https://github.com/mariozechner/pi-ai now 404s. Replaced
both shapes of reference:
- The reference-style [piai]: definition now points at
https://github.com/badlogic/pi-mono/tree/main/packages/ai
(the multi-provider LLM API package).
- Inline links whose visible text is the CLI tool 'pi' or 'Pi' now
point at
https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent
(the interactive coding-agent CLI), so a reader clicking 'pi' in
the daemon-discovery section lands on the actual binary's docs.
Affected: README.md and 10 translated READMEs, plus docs/spec.md,
docs/architecture.md, docs/references.md, docs/roadmap.md.
Closes#275.
* fix(daemon): expand $HOME / ${HOME} in OD_DATA_DIR (#390)
Some launchers (systemd unit files, NixOS modules, certain Docker
entrypoints) pass OD_DATA_DIR with a literal '$HOME' or '${HOME}'
because no shell ever expands them. resolveDataDir previously only
handled '~/' shorthand, so '$HOME/.open-design' fell through to
path.resolve(PROJECT_ROOT, '$HOME/.open-design') and produced paths
like /opt/open-design/$HOME/.open-design.
resolveDataDir now expands '~', '~/...', '$HOME', '$HOME/...',
'${HOME}', and '${HOME}/...' to os.homedir() before the absolute /
relative branch runs. Rebuilds via path.join so the platform separator
is correct on Windows even when the input used forward slashes.
Tests: 7 unit tests cover empty/undefined, '~', '~/...', '$HOME',
'$HOME/...', '${HOME}/...', absolute paths, and relative paths.
Closes#390.
* fix(daemon): accept backslash separators + hermetic resolve-data-dir tests
Round 1 review feedback on PR #530.
The previous regex only matched forward-slash separators, so a Windows
launcher passing OD_DATA_DIR=$HOME\.open-design or ${HOME}\.open-design
fell through to path.resolve(projectRoot, ...) and produced a directory
named $HOME or ~ under projectRoot. The regex now accepts both forward
and back slashes for the home-prefix separator.
The previous tests called the real resolveDataDir against literal
~/od-test, $HOME/od-test, etc., which created and write-checked
directories under the developer's or CI runner's actual home. The tests
now stub os.homedir() with vi.spyOn to a per-test mkdtemp directory and
remove it in afterEach, so no test ever writes outside its own sandbox.
Added explicit fixtures for the Windows backslash forms ($HOME\od-test,
${HOME}\od-test, ~\od-test) so launcher coverage stays cross-platform.
12/12 resolve-data-dir tests pass, daemon typecheck clean.
* fix(docs,daemon): apply pi-mono links to README.es and await test cleanup
Round 2 review feedback on PR #530.
README.es.md was added in upstream #552 after my pi-mono link sweep
landed, so the daemon-discovery paragraph (line 222), the [piai]
reference (line 684), and the Pi table row (line 709) still pointed
at the broken https://github.com/mariozechner/pi-ai URL. Applied the
same replacements: the [piai] ref now points at packages/ai, and the
inline Pi link now points at packages/coding-agent. Spanish readers
get the same coverage as the other 11 locales.
The absolute-path test in tests/resolve-data-dir.test.ts dropped its
fixture via void rm(abs, ...), so a failed async removal could leak
rdd-abs-* directories from the suite. The test is now async and
awaits the rm in the finally block, matching the awaited cleanup in
afterEach. 12/12 resolve-data-dir tests still pass, daemon typecheck
clean.
* fix(daemon): share $HOME expander between OD_DATA_DIR and OD_MEDIA_CONFIG_DIR
Round 3 review feedback on PR #530.
resolveDataDir (server.ts) now expands $HOME / ${HOME} / ~, but
media-config.ts had its own resolveOverrideDir that only handled ~/.
Because configFile() falls back to OD_DATA_DIR when OD_MEDIA_CONFIG_DIR
is unset, setting OD_DATA_DIR=$HOME/.open-design split state: SQLite,
projects, and artifacts went to the expanded path while
media-config.json stayed under <projectRoot>/$HOME/.open-design.
Stored provider keys then appeared missing on the next read.
Extracted the home-prefix expansion into apps/daemon/src/home-expansion.ts
so resolveDataDir and resolveOverrideDir share one resolver. Both now
recognize ~ / $HOME / ${HOME} (bare tokens) and ~/, ~\, $HOME/, $HOME\,
${HOME}/, ${HOME}\ (prefix forms with either separator).
Three new media-config routing tests cover the OD_DATA_DIR fallback for
$HOME/..., ${HOME}/..., and the OD_MEDIA_CONFIG_DIR explicit-override
$HOME/... case so the co-location guarantee is locked down by tests.
Daemon typecheck clean. Tests pass on Linux CI; the existing pattern in
the file uses process.env.HOME which os.homedir() reads on POSIX.
Resolve-data-dir tests stay hermetic via vi.spyOn.
* docs(daemon): media-config comments reflect full $HOME / ${HOME} expansion
Round 3 review feedback on PR #530 (lefarcen, P3 non-blocking).
The file-header and resolveOverrideDir() function comment said only
~/ expands. Updated both to mention the shared expandHomePrefix()
helper and the full set of forms it handles (~, $HOME, ${HOME} with
either separator), so a future reader does not need to chase the
implementation to understand what env values are accepted.
* test(daemon): stub os.homedir() in media-config routing tests
Round 4 review feedback on PR #530.
The new $HOME / ${HOME} routing tests relied on process.env.HOME being
read by os.homedir(), which works on POSIX but is unreliable on Windows
(Node prefers USERPROFILE / profile APIs there). The tests would expand
to the real user home while fixtures were written under the per-test
homeDir, causing platform-specific failures in the same area this PR
is making cross-platform.
The inner describe block now stubs os.homedir() via vi.spyOn to return
the per-test homeDir, matching the pattern in resolve-data-dir.test.ts.
Restored in afterEach. The four $HOME-form routing tests now pass on
both POSIX and Windows.
Daemon typecheck clean. The two OAuth fallback test failures unrelated
to this change (real ChatGPT/Codex tokens in the local env) remain
out-of-scope.
* fix(i18n): drop duplicate uk.ts promptTemplates keys after rebase
Upstream #674 added the same Ukrainian translations my earlier
commit added. The rebase landed both copies; tsc rejects duplicate
property names. Drop my copies so #674 (which is now upstream) is
the single source for these keys.
---------
Co-authored-by: Nagendhra <nagendhra405@gmail.com>
* feat: add accent color control and launcher for Open Design
* fix: remove launcher binary from PR
* test: cover accent appearance edge cases
---------
Co-authored-by: ferasbusiness666 <ferasbusiness666@users.noreply.github.com>
* feat(skills): add 5 Orbit briefing templates
Introduces a new "orbit" scenario family in the Examples gallery for
morning-briefing surfaces. Each template lives at the top of "我的设计"
and aggregates yesterday's connector activity into a single page.
- orbit-general: adaptive bento dashboard that fans across 12-16
connectors, where each module picks its own UI form by data type
(list / avatar stack / status ring / heatmap / file grid / alert
card / kanban / etc.)
- orbit-github: GitHub-flavored single-connector digest mirroring the
Notifications + PR-diff visual language
- orbit-gmail: Gmail-flavored digest rendered as a Daily Digest email
inside the three-pane inbox
- orbit-linear: Linear-flavored digest in the dark Inbox + cycle-
progress layout
- orbit-notion: Notion-flavored digest authored as a native Notion
page (callout / toggle / database table)
The new scenario value 'orbit' surfaces as a filter pill in
ExamplesTab automatically; no UI code change required.
* fix(skills): reframe Orbit skill descriptions as pipeline-triggered
The original descriptions framed each skill as a standalone "X-flavored
briefing template" the user picks. They are actually skills the Orbit
daily-digest pipeline selects automatically based on which connectors
the user has authenticated, then runs against live connector data.
Rewrites both `description` and `example_prompt` for all 5 templates:
- orbit-general: invoked when 2+ connectors are connected; aggregates
the past 24h across every authenticated source
- orbit-github / orbit-gmail / orbit-linear / orbit-notion: invoked
when the named connector is the user's only connection (or scope is
explicitly limited to it); pulls the past 24h from that connection
alone
All 5 now state explicitly that they are not user-triggered — the
Orbit scheduler invokes them.
* feat(examples): add Orbit pill to the mode filter row
Surfaces the Orbit briefing skills as a top-level "type" filter in the
Examples gallery, alongside Prototype · Desktop / Mobile / Slide deck /
Docs & templates. Filter matches skills with scenario === 'orbit'.
- ExamplesTab: extend ModeFilter and MODE_PILLS with 'orbit'; teach
matchesMode and modeCounts about it
- i18n: add 'examples.modeOrbit' to Dict and to all 16 locale files
('Orbit' is left untranslated as a brand name)
* polish(orbit-general): real Figma preview image + revised comment
Replaces the empty gray placeholder in the Figma module with an
Unsplash UI-design photo, and rewrites the mock comment to read like
a substantive design-review note rather than a nit about button
placement.
* feat(examples): eager-load card previews via IntersectionObserver
Card previews previously only loaded on hover, leaving the example
gallery showing 'Hover to preview' placeholders for everything below
the fold. Now each card observes the viewport and prefetches its HTML
800px before scrolling into view, so the iframe is ready by the time
the user reaches it.
Hover remains as a fallback path (and for browsers without
IntersectionObserver, the card loads immediately on mount).
Also reverts the Unsplash photo on the orbit-general Figma module
back to the gray placeholder — the stock image semantically misread
as a Photoshop screenshot rather than a Figma artboard.
* feat(orbit-general): drop Figma connector module
Removes the Figma bento card and its scoped CSS, plus the orphaned
Top-3 entry that referenced a Figma comment. Reassigns Top-3 #2 to
a Notion document review so the priority list stays aligned with
the connectors actually rendered.
* i18n(skills): translate Orbit example prompts to English
The example_prompt is what gets injected into the chat input when a
user clicks 'Use this prompt', and is read by the agent verbatim. It
should match the SKILL.md description language (English), not the UI
locale. Replaces the Chinese drafts with English equivalents across
all 5 Orbit skills, and drops the Figma reference from orbit-general
since that connector module was removed earlier.
* fix(skills): rewrite Orbit SKILL.md bodies with reproducible specs
Earlier the bodies were too abstract (only a connector→UI mapping
table and a one-line style note), so agents running the skill could
not reproduce the shipped example.html and got stuck in long retries.
Each SKILL.md body now contains:
- exact color tokens lifted from the example.html
- type stack and font sizes
- a section-by-section page spec (top-to-bottom)
- chip / pill / icon rendering rules
- forbidden list
The example_prompt is collapsed back to a one-line user intent so the
skill body is the source of design truth.
Covers all 5 templates: orbit-general, orbit-github, orbit-gmail,
orbit-linear, orbit-notion.
* feat(orbit): make every connector item clickable
Each Orbit briefing template now links its rows / cards to the matching
source URL so users can jump straight from the morning digest to the
underlying connector.
- orbit-general: each bento card gains an 'Open in {connector} ↗' CTA
built from a connector→URL map; each Top 3 card becomes an anchor
- orbit-github: every event row opens the corresponding github.com
pull/issue URL parsed from the row identifier; the header logo links
to the repo
- orbit-linear: each issue row gains a small ↗ button that opens
linear.app/{team}/issue/{ID}
- orbit-gmail: action and reply buttons jump to a Gmail search URL
scoped to the sender
- orbit-notion: page-link spans wrap as anchors and database rows are
click-to-open against notion.so
All links use target="_blank" rel="noopener noreferrer".
* fix(skills): force agents to mirror example.html 1:1
Earlier skills told the agent the example was 'source of truth' but
left phrasing soft, so agents felt free to add extra UI elements
(snoozed-mail row, extra yellow stars on inbox rows, etc.) that
were not in example.html.
Each Orbit SKILL.md now opens with a 'Source-of-truth protocol' that
forces the agent to:
1. read example.html before writing any output
2. mirror its DOM structure / class names / module count / element
order 1:1
3. only refresh mock values; never invent additional UI elements,
rail entries, sections, badges, or chrome ornaments
The reference sections that follow stay informative for tokens and
visual language but are explicitly demoted from spec to commentary.
* fix(orbit-gmail): remove three-pane / left-rail / inbox-list claims
The example.html is a single-column page: Gmail top header + the
opened Orbit Daily Digest email (toolbar / subject / sender / digest
body / reply bar). Earlier copy described a Gmail three-pane app with
Compose button, label list, Categories tabs, and an inbox listing —
none of which exist in the actual asset.
- example_prompt: drops 'three-pane inbox' phrasing
- description: same
- body: rewrites Page sections to mirror the real header → email-chrome
layout, top to bottom; explicitly forbids left rail, inbox list, and
Categories tab strip
* feat(orbit): forbid external design systems in all 5 skills
Each Orbit briefing template ships its own complete visual language
baked into example.html (Gmail / GitHub / Linear / Notion / Open
Orbit's editorial bento). Adds an explicit 'Design system policy'
block telling the agent to:
- ignore any DESIGN.md attached to the active project
- ignore brand tokens or Figma files supplied via chat
- use exclusively the colors / fonts / radii from example.html
This is a hard constraint: an Orbit briefing must look like the
connector it represents, not like the user's brand.
* feat(newproj): hide design-system picker for skills that opt out
Skills can declare 'od.design_system.requires: false' in SKILL.md to
opt out of DESIGN.md injection (the Orbit briefing skills do this —
their example.html ships with a complete connector-native visual
language). When the active default skill for a tab opts out, hide the
design-system picker so we don't ask the user to attach a brand we'll
then ignore.
Existing tabs that don't host a default skill (template, other) keep
the picker. The check only fires for prototype / live-artifact / deck.
* review: address P2 reviewer feedback
P2 — Connector family coverage gaps (orbit-general):
Adds Finance, CRM/Sales, Support, Analytics, Infrastructure, Security
rows to the connector→UI mapping table (now 16 families). Adds a
'Fallback heuristics' subsection so unknown connectors are routed by
data shape (numbers + time series → Alerts, rows + status field →
Task mgmt, etc.).
P2 — 'Forbidden' rules too vague (all 5 skills):
Rewrites every Forbidden section as a paired 'Don't / Do' constraints
table so each negative is paired with a concrete positive. Replaces
obvious bans (lorem ipsum) with substantive ones (real-shaped mock
copy, plausible identifiers, dev-team label hues, etc.).
* ci: register orbit skills in de/ru/fr en-fallback lists
The localized-content coverage test asserts that every skill in
skills/ is either translated or explicitly declared as falling back
to English in the LOCALIZED_CONTENT_IDS bundle. The 5 new orbit
skills weren't in any bundle, so the workspace validation job failed
on the de/ru/fr coverage assertions.
Adds the 5 orbit-* ids to DE/FR/RU_SKILL_IDS_WITH_EN_FALLBACK so
those locales explicitly fall back to the SKILL.md English copy
(matching the minimal-change posture chosen earlier in this PR).
* feat(media): add Nano Banana image provider
* fix(media): support Gemini API key headers for Nano Banana
* refactor(media): move Nano Banana model override flag into provider metadata
* fix(web): improve settings dialog scroll behavior
- Remove double scroll containers by changing modal-body overflow from auto to hidden, letting only settings-content handle scrolling
- Add min-height: 0 to settings-content and settings-sidebar to allow proper shrinking in grid layout
- Add overscroll-behavior: contain to prevent scroll chaining (scroll bleed-through to parent page)
- Add overflow-y: auto to settings-sidebar for cases where navigation items exceed viewport height
These changes fix the nested scroll issue that caused confusing scroll behavior and prevent content overflow on smaller viewports.
* fix(i18n): add missing Ukrainian translations for promptTemplates
Add promptTemplates.allSources and promptTemplates.sourceFilterAria translations to fix TypeScript error.
* feat(prompt-templates): add 11 HyperFrames video prompts and surface media generation in README
Adds eleven `hyperframes-*` prompt templates under `prompt-templates/video/`,
each one a concrete brief with scene-by-scene timing, GSAP eases, palette,
and the HyperFrames non-negotiables (deterministic, paused timelines,
entrance-only motion, lint/inspect commands). Archetypes covered:
- minimal product reveal (5s, 16:9)
- SaaS product promo (30s, 16:9, Linear/ClickUp-style)
- TikTok karaoke talking-head (9:16, TTS + word-synced captions)
- brand sizzle reel (30s, beat-synced kinetic typography)
- animated bar-chart race (NYT-style data infographic)
- Apple-style flight map route (origin → destination)
- 4s cinematic logo outro
- $0 → $10K money counter hype (9:16)
- 3-phone app showcase
- 9:16 social overlay stack (X · Reddit · Spotify · Instagram)
- 15s website-to-video pipeline
Each template uses `model: "hyperframes-html"`, real catalog-block thumbnails
from HeyGen's CDN as previewImageUrl, and source attribution to
`heygen-com/hyperframes` (Apache-2.0).
README also gets a new **Media generation** section between *Visual directions*
and *Beyond chat*, plus a new row in the *At a glance* table. The section
documents the three model families currently surfaced as templates
(gpt-image-2, Seedance 2.0, HyperFrames) with example galleries — gpt-image-2
thumbnails, Seedance MP4-linked thumbnails, and the 11 HyperFrames tiles —
and notes the wider model coverage (Kling, Veo, Sora, MiniMax, Suno, Udio,
Lyria, TTS) already wired in `VIDEO_MODELS` / `AUDIO_MODELS_BY_KIND` and
open for community templates.
* i18n(de): register new HyperFrames templates, categories, tags
Adds German titles/summaries for the 11 new hyperframes-* video templates
plus the Product/Marketing/Data/Travel/Branding/Short Form categories and
hyperframes/title-card/sizzle/etc. tags they introduce, so the German sync
guarantees enforced by apps/web/src/i18n/content.test.ts hold.
* docs(readme): sync Media generation section to de / ja / ko / zh-CN; bump counts to 93 (43 + 39 + 11)
Mirrors the English Media generation row + section into the four locale READMEs
(README.de.md, README.ja-JP.md, README.ko.md, README.zh-CN.md), translating
prose / table headers / captions while keeping the gpt-image-2, Seedance MP4,
and HyperFrames catalog-block thumbnails identical across all five locales so
the galleries render the same images.
Counts updated to reflect current main (after rebase): 43 gpt-image-2 + 39
Seedance + 11 HyperFrames = 93 prompts total. The English README's At-a-glance
row, intro paragraph, and gallery sub-headers now read "sample of 43" /
"sample of 39" / "11 ready-to-replicate templates" — locales follow.
Resolves the Codex review's German-i18n flag end-to-end: README copy is in
sync, and the German content map (DE_PROMPT_TEMPLATE_*) was already extended
in the prior commit on this branch.
* feat(prompt-templates): video previews + provider badge + source filter for HyperFrames
- Add `previewVideoUrl` to all 11 HyperFrames video templates so the preview
modal plays the real catalog clip instead of falling back to a static image.
- Add a per-card provider badge (top-left thumbnail chip) keyed off
`source.repo`. HyperFrames cards get a HeyGen-accent gradient so they are
identifiable at a glance; other repos get a neutral pill.
- Add a Source filter dropdown next to Category in PromptTemplatesTab,
populated from the small enumerated repo set (HyperFrames, Seedance 2,
GPT Image 2, Open Design). Auto-hides when only one source is present.
The text search now also matches the provider name.
- Wire i18n keys `promptTemplates.allSources` and
`promptTemplates.sourceFilterAria` across all 9 locales.
* feat(web): add Cmd/Ctrl+P quick file switcher
A keyboard-driven file palette overlaid on the workspace. Press Cmd/Ctrl+P
anywhere in the project view; type to fuzzy-filter the file list, ↑/↓ to
navigate, Enter to open in a tab, Esc to dismiss. With an empty query the
palette surfaces recents (per-project, localStorage) followed by the rest
of the file list sorted by mtime.
Adds:
- apps/web/src/components/QuickSwitcher.tsx: palette UI and matcher
- apps/web/src/quickSwitcherRecents.ts: per-project recents store
- index.css: scoped .qs-* styles using existing design tokens
- i18n: 6 new keys translated across all 16 locale files
Wires into FileWorkspace's existing openFile() so recents and tab state
behave identically to opening from DesignFilesPanel. Capture-phase keydown
beats the browser's print dialog. No backend changes; uses the files prop
already passed to FileWorkspace.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(web): address QuickSwitcher review feedback
Three fixes from the PR review:
- z-index: bump .qs-overlay from 200 to 1500 so the palette renders in
the modal tier (alongside prompt-template-modal-overlay) instead of
behind context menus and popovers (which sit at 200).
- Arrow-key guard: skip setCursor when matches is empty. Without this,
pressing ↓ on a no-results query set the cursor to -1, making the
highlight selector miss every row on the next render.
- Tests: add 19 unit tests covering scoreMatch ranking tiers, render
output (empty state / row count / kbd hints / placeholder), and the
full recents lifecycle (cap at 6, dedupe-on-push, corrupt-JSON
recovery, per-project scoping, quota-exceeded no-op). Vitest stays
on the node env via a small in-memory localStorage stub.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(web): QuickSwitcher review — wrap, IME, platform gate
Three follow-ups from @mrcfps's review on #556:
- ArrowUp/ArrowDown now wrap at list bounds (last → first, first → last)
via modulo arithmetic in a new pure helper `nextCursor(current, total,
direction)`. Previously they clamped, which contradicted the wrap
behavior the PR test plan promised. Pulled into a pure function so
boundary cases are unit-testable without simulating keyboard events.
- Palette's onKeyDown now early-returns on `e.nativeEvent.isComposing`,
so users typing CJK file names through an IME keep ↑/↓/Enter for
candidate navigation instead of having them steered by the palette.
The global Cmd/Ctrl+P opener already had the equivalent guard.
- Global keydown is now platform-gated: macOS responds only to metaKey,
win/linux only to ctrlKey. Previously both fired everywhere, which
meant Ctrl+P on macOS was stealing native readline "previous line" in
text fields (and the chat composer).
Tests: +6 unit tests for `nextCursor` covering forward/backward wrap,
mid-list moves, empty list (no division-by-zero), and single-item
no-op. Suite now 258 passing (up from 252).
Verified live: ↓ from last row → first row; ↑ from first row → last
row, in a mocked-project Playwright harness.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat(web): add skills & design systems management page in settings
Add a new "Library" section in Settings that lets users browse, search,
preview, and enable/disable skills and design systems. Disabled items are
excluded from the create-project picker. Phase 1 — browse/toggle only.
Closes#497
* fix(web): persist empty disabled lists and deduplicate DS preview
Use empty array instead of undefined when all items are re-enabled so
the daemon merge clears the key. Move DS preview panel outside the
category group loop so it renders once, not per group.
* fix(web): address review feedback on library settings
Clear disabled lists on invalid daemon writes, memoize enabled item
filters in App.tsx, and guard preview fetch against rapid-click race
conditions.
* fix(web): hydrate disabled lists from daemon and keep full lists in ProjectView
Merge daemonConfig.disabledSkills/disabledDesignSystems during bootstrap
so the values survive localStorage resets. Pass unfiltered skills and
design systems to ProjectView so existing project metadata resolves
correctly.
Add backward compatibility for historic OpenCode CLI data:
- Match both 'TodoWrite' and 'todowrite' tool names
- Fixes rendering of TodoWrite cards from persisted chat history
Scope: 1 line change, no other files modified
Co-authored-by: bojiehuang <bojiehuang@bojiehuangdeMacBook-Pro.local>
* docs: add live artifacts implementation spec
* docs: align live artifacts implementation plan
* Ralph iteration 1: work in progress
* Ralph iteration 2: work in progress
* Ralph iteration 3: work in progress
* Ralph iteration 4: work in progress
* Ralph iteration 5: work in progress
* Ralph iteration 6: work in progress
* Ralph iteration 7: work in progress
* Ralph iteration 8: work in progress
* Ralph iteration 9: work in progress
* Ralph iteration 10: work in progress
* Ralph iteration 11: work in progress
* Ralph iteration 12: work in progress
* Ralph iteration 13: work in progress
* Ralph iteration 14: work in progress
* Ralph iteration 15: work in progress
* Ralph iteration 16: work in progress
* Ralph iteration 17: work in progress
* Ralph iteration 18: work in progress
* Ralph iteration 19: work in progress
* Ralph iteration 20: work in progress
* Ralph iteration 21: work in progress
* Ralph iteration 22: work in progress
* Ralph iteration 23: work in progress
* Ralph iteration 24: work in progress
* Ralph iteration 25: work in progress
* Ralph iteration 26: work in progress
* Ralph iteration 27: work in progress
* Ralph iteration 28: work in progress
* Ralph iteration 29: work in progress
* Ralph iteration 30: work in progress
* Ralph iteration 31: work in progress
* Ralph iteration 32: work in progress
* Ralph iteration 33: work in progress
* Ralph iteration 34: work in progress
* Ralph iteration 35: work in progress
* Ralph iteration 36: work in progress
* Ralph iteration 37: work in progress
* Ralph iteration 38: work in progress
* Ralph iteration 39: work in progress
* Ralph iteration 40: work in progress
* Ralph iteration 41: work in progress
* Ralph iteration 42: work in progress
* Ralph iteration 43: work in progress
* Ralph iteration 44: work in progress
* Ralph iteration 45: work in progress
* Ralph iteration 46: work in progress
* Ralph iteration 47: work in progress
* Ralph iteration 48: work in progress
* Ralph iteration 49: work in progress
* Ralph iteration 50: work in progress
* Ralph iteration 51: work in progress
* Ralph iteration 52: work in progress
* Ralph iteration 53: work in progress
* Ralph iteration 54: work in progress
* Ralph iteration 55: work in progress
* Ralph iteration 56: work in progress
* Ralph iteration 57: work in progress
* Ralph iteration 58: work in progress
* Ralph iteration 59: work in progress
* Ralph iteration 60: work in progress
* Ralph iteration 61: work in progress
* Ralph iteration 62: work in progress
* Ralph iteration 63: work in progress
* Ralph iteration 64: work in progress
* Ralph iteration 65: work in progress
* Ralph iteration 1: work in progress
* Ralph iteration 2: work in progress
* Ralph iteration 3: work in progress
* Ralph iteration 4: work in progress
* Ralph iteration 5: work in progress
* Ralph iteration 6: work in progress
* Ralph iteration 8: work in progress
* Ralph iteration 9: work in progress
* Ralph iteration 17: work in progress
* Add Composio-backed connectors
* Add Composio-backed connector catalog
* Fix connector callback flow
* Update live artifact connector refresh
* Fix live artifact refresh updates
* Improve live artifact viewer toolbar
* Refine live artifact source tabs
* Expand Composio connector catalog
* Improve Composio connector browsing
* Fix artifact refresh source safety checks
Generated-By: looper 0.4.1 (runner=fixer, agent=opencode)
* Fix live artifacts PR feedback
Generated-By: looper 0.5.0 (runner=fixer, agent=opencode)
* Fix live artifact preview CORS validation
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Fix connector OAuth IPv6 loopback hosts
Allow bracketed IPv6 loopback Host headers when deriving connector OAuth callback URLs so IPv6-bound daemons can complete connection flow.
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Preserve live artifact refresh permissions
Respect explicit refresh permission choices during live artifact create and update flows so revoked connector sources remain gated.
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Fix live artifact preview cache freshness
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Fix live artifact refresh validation
Guard manual refreshes with local daemon checks and reject daemon_tool sources without a toolName before refresh execution.
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Fix Composio credential invalidation
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Fix live artifact CORS methods
Generated-By: looper 0.0.0-dev (runner=fixer, agent=opencode)
* Fix workspace validation
Restore media config test isolation under Vitest setup data-dir overrides and add the missing French live artifact display copy so the workspace test suite stays aligned.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode)
* Fix connector safety filtering
Keep agent-preview connector listings aligned with execution safety policy and prune stale Composio OAuth state records before they accumulate.
Generated-By: looper 0.5.2 (runner=fixer, agent=opencode)
* Fix agent runtime cleanup
Generated-By: looper 0.5.2 (runner=fixer, agent=opencode)
* Fix live artifact daemon access
Validate local-only live artifact routes against the peer socket address and pass daemon-resolved CLI paths to ACP MCP descriptors.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode)
* Fix connector run limit pruning
Evict stale connector rate-limit buckets so long-lived daemon processes do not retain per-run entries indefinitely.\n\nGenerated-By: looper 0.5.2 (runner=fixer, agent=opencode)
* Fix connector compact schemas
Generated-By: looper 0.5.2 (runner=fixer, agent=opencode)
* Improve connector connection feedback
* Adjust connector gate positioning
* Fix live artifact refresh commits
Avoid marking refresh candidates failed after snapshot or state persistence errors by deferring live artifact mutations until the durable refresh metadata is written. Also align connector OAuth callback host validation with daemon loopback handling.\n\nGenerated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* Improve connector search relevance
* fix(daemon): harden connector connection state
Require loopback daemon validation before connector connect side effects and only clear provider-owned connector statuses during credential reset.
Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* fix(daemon): guard connector disconnect route
Require local daemon request validation before connector disconnect side effects.
Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* fix(daemon): guard composio config updates
Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* fix(daemon): dispatch live artifacts mcp first
Route the live-artifacts MCP server before the generic MCP CLI so od mcp live-artifacts starts the dedicated server instead of failing generic argument parsing.\n\nGenerated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* fix(daemon): handle integer connector schemas
Allow JSON Schema integer connector inputs while preserving fractional-value validation so generated connector tool schemas accept valid page sizes and limits.
Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* fix: align live artifact refresh error codes
Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* Fix live artifact connector refresh flow
* Update live artifact design cards
* Add beta badge to live artifact form
* Remove live artifact tile model
* Fix live artifact refresh sync
* Fix live artifact MCP refresh durability
Generated-By: looper 0.5.4 (runner=fixer, agent=opencode)
* Fix live artifact refresh safety
Enforce persisted refresh opt-out and connector auto-read gating before refresh sources execute.
Generated-By: looper 0.5.5 (runner=fixer, agent=opencode)
* chore: enforce test directory conventions
Move package, app, and tool tests out of src and add guard enforcement so source directories stay source-only.
* ci: use guard and package-scoped tests
Run the new repository guard in CI and keep test execution aligned with package-scoped commands after removing root aliases.
* ci: align stable release guard check
Use the new repository guard in stable release verification after replacing the residual-JS-only script.
* chore: tighten test layout enforcement
Enforce sibling tests directories, typecheck moved test suites with dedicated configs, and refresh remaining guidance that pointed at src-based tests.
* chore: clarify no-emit test tsconfigs
Explicitly disable declaration-only emit in test tsconfigs so review tooling sees they are no-emit typecheck configs.
* feat(daemon): add link code folder support for agent context
Users can now link local code directories to a project so the AI agent
reads their source code via --add-dir when generating designs. The
import menu's "Link code folder" item opens a native OS folder picker,
and linked folders appear as removable chips below the chat input.
- Add linkedDirs field to ProjectMetadata contract
- Add POST /api/dialog/open-folder endpoint (osascript/zenity/PowerShell)
- Add validateLinkedDirs with path safety checks (absolute, exists, blocklist)
- Append linked dirs to extraAllowedDirs in startChatRun
- Add system prompt hint listing linked code folders
- Render linked folder chips in ChatComposer with add/remove
- Add i18n strings for all 16 locales
- Add 8 unit tests for validateLinkedDirs
* fix: address PR review feedback
- Add JSDoc type annotations to validateLinkedDirs for strict mode
- Check path.isAbsolute before resolve to catch relative inputs
- Allow linking when projectMetadata is undefined (default to prototype)
- Remove redundant PATCH in ProjectView callback
* fix: use inline TS annotations instead of JSDoc in linked-dirs.ts
* fix(daemon): harden linked-dirs validation against security bypasses
- Resolve symlinks with realpathSync.native before checking blocklist
- Reject filesystem root (/) and drive roots as linked dirs
- Canonicalize blocklist entries to handle macOS /etc -> /private/etc
- Validate linkedDirs on project creation, not just PATCH
- Re-validate persisted linkedDirs in startChatRun before use
- Add tests for root, symlink-to-blocked-dir, and realpath resolution
* fix: narrow union type before accessing .error in tests
The module-level Map cached slide state per project+file key but never
evicted entries. In long-lived sessions with many projects, this grows
without bound. Add a 64-entry cap with FIFO eviction.
Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
The 380px sidebar gives the 3-column aspect grid only ~92px per cell. The
flex-row card layout reserved 34px for the glyph plus 7px gap, leaving
~31px for the label — but "Landscape"/"Portrait" at 13px / weight 650 are
~75px wide. Without `min-width: 0` on the flex/grid items, the strong
text refused to shrink and overflowed, so each card's label visually
covered the next card's glyph.
Switch the aspect cards to a column layout (glyph above, label + ratio
below) so the label has the full card width. Add the missing
`min-width: 0` on `.newproj-option-card` and `.aspect-copy` as a defense
against future long-text regressions, and rebalance glyph dimensions and
font sizes to match the tighter cards.
Closes#242