* AMR: normalize Vela's kimi_k2_7_code id to kimi-k2.7-code
* fix(amr): normalize Vela JSON catalog ids on the live fetchModels path
parseVelaModelJson (used by fetchVelaRemoteModelsWithRetry) was not
calling normalizeVelaModelId, so raw ids like public_model_kimi_k2_7_code
from `vela model list --format json` reached the model picker and
session/set_model unchanged.
Move the normalization call into parseVelaModelJson (mirroring what
parseVelaModels already does for the legacy `vela models` path), update
the existing unit test to assert normalized output, and add a regression
that exercises the full catalog-fetch + session/set_model flow.
Also removes four root-level scratch files (SOLVE_BRIEF.md,
CLAIM-COMMENT.md, PR-DESCRIPTION.md, PR-TITLE.md) that were local
agent working material unrelated to the daemon bugfix.
Fixes#4410
- Add a Country / Region dropdown (full ISO list localized per locale at
build time via Intl.DisplayNames), preselected from the visitor's
browser locale (zh-CN -> CN, bare languages maximized), submitted as
the existing `location` field shown on the Feishu lead card.
- Turn the use-case chips into a single-select dropdown and broaden the
vocabulary from 7 to 14 scenarios (brand/VI, social & e-commerce,
posters & print, video & motion, illustration, education, game assets).
- Add an Expected seats range dropdown (1-5 … 500+, submitted via the
existing `seats` field) alongside Team size, drop the Name field, and
make Company optional.
- Drop the 'Not sure yet' budget option.
- Author the page copy for all active locales (ja/ko/de/fr/ru/es/pt-br/
it/tr) instead of falling back to English.
- Compact the form: selects pair up two per row (subgrid keeps the
controls aligned when a wrapped label makes the pair uneven), and the
page claws back most of the shared 140px sub-page top padding.
- Keep the /contact-sales enterprise contract in sync (team-size +
seat-range + budget enums + use case required; name/company no longer
required), extend the use-case allowlist, and map seat codes to
readable labels on the Feishu card.
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Restore the secondary CTA on the story's hero and final cards, pointing to
/enterprise/ (Workspace for Teams early access). The final section already
carried the team pitch copy but had no button; the hero gets a light ghost
secondary next to Download. Localized across the English page and all 17
locale variants (machine-translated button label — worth a native/team check
before merge).
Co-authored-by: ScarletttMoon <scarletttmooon@gmail.com>
Adds the 0.13.0 release blog post pulled from the GitHub release notes
(open-design-v0.13.0, 116 PRs / 26 contributors / 6 days), matching the 0.11.0
and 0.12.0 posts: full English long-form body, 10-locale i18n block
(zh/ja/ko/de/fr/ru/es/pt-br/it/tr), and three on-brand illustrations (cover +
session-resume + exports figures). Wires the cover into the blog index.
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* Add Shanghai AI workshop blog post
* Add Chinese localization for Shanghai workshop post
* Localize Shanghai workshop post
---------
Co-authored-by: tuolaji <tuola@tuolajideMacBook-Air.local>
* feat(analytics): complete composer context-sources tracking (#4869 follow-up)
Close the tracking gaps left by the composer context sources feature:
- home: reference-project pick now carries resource_kind/resource_id
(workspace/reference-project) instead of a bare plus_pick, and link
local code aligns with the chat panel's plus_pick workspace/local-code
(was mis-mapped to working_dir, which is the separate working-dir
picker feature)
- both surfaces: track the figma_help row, opening the design-system
picker from the + menu (design_system_open), and the two new modals'
exposure (project_reference_modal / figma_help_modal surface_view)
- home: context chips (plugin / mcp / connector / workspace) removals
now emit context_remove, mirroring the chat panel
- new context_link_result event closes the linking funnel: success /
cancelled / failed per attempt, with linked-project count
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(analytics): track plus-menu submenu opens and search usage
Complete the panel inventory: every row of the composer + menu now has
an event on both surfaces. Adds plus_submenu_open (connector / plugin /
skill / mcp flyout opened — fires on submenu transition, not repeated
hovers) and plus_search (first keystroke in a flyout search box, once
per open, query text never sent). The Design-toolbox row keeps its own
design_toolbox_open and is excluded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(landing-page): add 2 community tutorials from 2026-07-01 review digest
Onboards the two YouTube candidates scoring >=60 in the daily Feishu review
digest (2026-07-01): 'J'abandonne Claude Design...' (84) by Jeremy DE CAMPOS
and 'Claude's NEW Design Update is INSANE!' (64) by Parth Jadav. Generated via
scripts/youtube-tutorials/generate-selected.ts.
* feat(landing-page): upgrade the 2026-07-01 tutorials to long-form + 10-locale i18n
Turns the two short catalogue stubs into full long-form SEO guides grounded in
each source video, with real workspace screenshots and a localized long-form
shard (zh/ja/ko/de/fr/ru/es/pt-br/it/tr) each:
- Jérémy DE CAMPOS (Review): rebuilds a real client SaaS mockup in Open Design
driven by the local Claude Code CLI (no metered tokens), clickable prototype,
design-system quality, and PRD handoff.
- Parth Jadav (Demo): hub-and-spoke workflow — one design system spun into five
on-brand assets, run free via a bring-your-own ChatGPT/Gemini engine.
Distinct angles, categories, and screenshot subsets from existing tutorials.
* feat(landing-page): backfill 7 long-form community tutorials (>=60 digest, Jun 3–30) + 10-locale i18n
Onboards seven previously-unactioned YouTube candidates that scored >=60 in the
daily Feishu review digest between 2026-06-03 and 2026-06-30, each as a full
long-form SEO guide grounded in its source video plus a 10-locale i18n shard
(zh/ja/ko/de/fr/ru/es/pt-br/it/tr):
- Dan Davies (Review) — full hands-on test of Open Design as a free alternative
- Code A Program (Demo) — the free open-source alternative walkthrough
- Sealos (Demo) — deploying Open Design to the cloud with Sealos Skills
- Fabricando Sua Ideia (Getting started, pt) — install + free setup
- 菲莉 AI 快報 (Getting started, zh) — a 5-minute feature overview
- AI Unlocked (Getting started) — install walkthrough
- Maestros da IA (Getting started, pt) — free unlimited alternative
Skipped four candidates as duplicative or too thin (two PurpleSchool Shorts that
duplicate the existing full-walkthrough tutorial, a 6-repo GitHub roundup, and a
50s teaser). Distinct angles, categories, and screenshot subsets throughout.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
Ollama Cloud BYOK still uses curated model lists because live discovery is disabled for that protocol. The public Ollama tags endpoint now includes newer cloud models reported in #4911, but the Settings/onboarding pickers still offered the older static set.
This updates both the generic Ollama suggestions and the managed Ollama Cloud preset so the picker surfaces the same recent models everywhere. The max-token override table is updated at the same time so newly selectable models do not fall through to the unknown-model 8192 token default.
Constraint: Ollama Cloud model discovery remains disabled in the app, so the picker still depends on curated tables
Rejected: Change existing cloud suffix/tag names from PR #4716 | that separate draft already owns broken existing IDs and changing them here would mix scopes
Confidence: high
Scope-risk: narrow
Directive: Keep SUGGESTED_MODELS_BY_PROTOCOL.ollama, the Ollama Cloud KNOWN_PROVIDERS models, and Ollama max-token overrides in sync when adding curated cloud models
Tested: pnpm exec vitest run -c vitest.config.ts tests/state/api-protocols.test.ts tests/state/maxTokens.test.ts tests/state/config.test.ts tests/components/SettingsDialog.execution.test.tsx --maxWorkers=2
Tested: pnpm --filter @open-design/web typecheck
Tested: pnpm guard
Tested: pnpm typecheck
Tested: pnpm --filter @open-design/web test
Not-tested: Live Ollama Cloud API request with a user key
Related: #4911
* test(web): cover stored-mode ZIP encoder CRC and central directory
* test(web): cover design-system audit repair-actions and chat-events dedup
* test(web): cover @mention parsing and agent label normalization
* test(web): cover error flattener, prompt-template categories, design-system sentinel
* fix(web): set ZIP UTF-8 filename flag (bit 11) for non-ASCII names
buildZip wrote UTF-8 filename bytes (TextEncoder) but left the
general-purpose bit flag at 0 in both the local and central headers, so
readers fall back to CP437 and mis-decode non-ASCII names like 日本.md.
Set general-purpose bit 11 (0x0800, EFS) in both headers when the
filename contains a non-ASCII byte; pure-ASCII archives are unchanged
(ASCII == CP437 == UTF-8), matching how Python/Go zip encoders behave.
Strengthen the UTF-8 test to assert the flag + filename in BOTH the
local and central-directory headers (parsed via EOCD), and add a case
asserting pure-ASCII names do not set the flag.
Addresses review feedback on #2451.
The /community/ hub, contributors, ambassadors, and moderators pages were
hand-written static HTML under public/community/ — English-only and outside
the Astro i18n routing, so every /<locale>/community/ variant 404'd.
Rebuild them as Astro routes rendered through sub-page-layout (real localized
header/footer, language switcher, canonical + hreflang, JSON-LD) with the
page-body design ported into a wrapper-scoped community.css so it neither
leaks into nor is broken by the shared site stylesheet. Copy moves into a
typed community-i18n tree: English base plus 10 Agent-translated locale
shards, merged with English fallback. Leaderboards render server-side from a
curated snapshot; good-first-issues, the copy button, and maintainer name
refresh stay client-side with localized strings.
- 4 pages x 11 locales, canonical + hreflang on every variant
- localize the header Community dropdown links (href) and add a footer
Community column
- sub-page-layout: optional mainClassName so full-bleed pages can opt out of
the centered .container shell
- remove the old static community/*.html + _styles.css + _site-nav.*
(ambassador avatar assets kept)
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* fix(landing-page): sync community static header with main nav
The /community/* pages render a hand-maintained static header
(public/community/_site-nav.js) that had drifted from the main site:
missing the Pricing nav item and the Open Design Cloud (AMR) sign-in
module, and its Community dropdown linked to same-page anchors
(/community/#contributors) instead of the real sub-pages.
- Add the Pricing nav item (/zh/pricing/) between Plugins and Resources.
- Add the .nav-account sign-in module (登录 + account menu) and port the
AMR auth block from header-enhancer.astro so it detects a cloud session,
drives popup login, and handles sign-out — matching every other page.
- Bring the matching .nav-account/.nav-signin/.nav-login-overlay styles
over into _site-nav.css from globals.css.
- Point the Community dropdown at the real sub-pages
(/community/contributors/, /ambassadors/, /moderators/) instead of
index anchors.
* fix(landing-page): return community AMR sign-in to locale-neutral root
The static community pages are the default (English) locale with no locale
prefix (<html lang="en">). Hardcoding the post-login home to /zh/ bounced a
signed-in user to the Chinese homepage. Mirror the main header's href('/')
semantics by using the locale-neutral root / instead.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(files): add HTML file version history
* fix(files): address version history review blockers
* fix(files): harden HTML version history
* fix(files): preserve deck version previews
* fix(files): serialize version history renames
* fix(files): reserve version history storage paths
* fix(files): rotate reused version history paths
* fix(files): surface HTML version capture failures
* fix(web): preserve upload display names
* fix(cli): reject invalid version source
* fix(web): label HTML view mode tabs
* fix(files): serialize HTML version captures
* feat(landing): align /pricing benefits with cloud plan modal + team lead-capture
Bring the /pricing plan cards in line with the Open Design Cloud subscription
modal, and turn the "Team" banner CTA into a real lead-capture flow.
Pricing cards (apps/landing-page):
- Fully-expanded benefit list per tier (drops the "includes all <tier>"
heading); credit + delivery rows now lead as ✓ bullets, with the limited-time
credit bonus badge (Pro +20% / Max +50%, effective $120 / $300) and a hover
tooltip explaining how a "design deliverable" is counted.
- Deliverable counts corrected to scale with the 6x/15x credit multiplier
(Pro 25-50, Max 70-140).
- Monthly tab shows a "save $X yearly" nudge that switches to the yearly tab;
default billing anchor is now yearly.
Team lead-capture:
- "Request team access" now opens a modal (mirrors the vela modal) instead of a
mailto. Only name + work email are required; posts to /contact-sales.
- Relax /contact-sales to require name + email only; company/team size/budget/
use case become optional and team size/budget accept free display strings.
Add country/region + expected-seats fields and surface them on the Feishu
card. Backward compatible with the existing /enterprise page.
Analytics (PostHog via __odTrack, autocapture stays off):
- pricing_interval_toggle (interval, via toggle|nudge), team_lead_open,
team_lead_submit (segmentation props, no PII), team_lead_error.
- Header sign-in funnel: sign_in_click, sign_in_success, sign_out_click,
cloud_console_open.
All copy is localized across the 10 supported locales.
* fix(landing): scope contact-sales relaxation to the pricing modal + reset lead form
Address review on #5005:
- Give the pricing "Request Team" modal its own source (`pricing_team`) and
restore the strict `/enterprise` contract: `source === 'enterprise'` still
requires company + a known team-size/budget enum + at least one use case, so
the full enterprise form no longer accepts blank/arbitrary leads. Only the
lightweight pricing flow is name+email-only. Add tests covering both paths.
- Reset the team lead modal on open (form.reset, hide success/error, re-enable
submit) so a prior success panel no longer strands the modal for the session.
* fix(landing): reject unknown contact-sales sources instead of relaxed fallthrough
Follow-up review on #5005: `source` fell back to "unknown" and only
`enterprise` was validated strictly, so a typoed/unknown source was accepted
with just name + email on a public write endpoint. Now non-allowlisted sources
return 400 `invalid_source`, and the relaxed name+email-only path is explicit to
`pricing_team` — every other allowlisted source (enterprise, client) keeps the
full contact-form contract. Added regression tests for an unknown source and
for `client` staying strict.
* fix(landing): canonical team-lead enums + accessible deliverables tooltip
Address the two non-blocking follow-ups on #5005:
- Team-lead selects now submit canonical, locale-independent enum values
(TEAM_SIZE_VALUES / BUDGET_VALUES) as the <option> value while keeping the
localized copy as the visible label, so `/contact-sales` + `team_lead_submit`
no longer persist locale-specific strings and the funnel aggregates across
locales. The Feishu card maps the enums back to readable text
(TEAM_SIZE_LABELS + pricing budget buckets added to BUDGET_LABELS).
- The deliverables ⓘ tooltip trigger is now a real <button> with an
aria-label and aria-describedby pointing at the tooltip's id (was a
tabindex'd svg that was also aria-hidden). Keyboard focus reveals the tooltip
via :focus-within, so the help text is exposed to keyboard + screen readers.
---------
Co-authored-by: rebel-nexu-zero[bot] <298160550+rebel-nexu-zero[bot]@users.noreply.github.com>
Follow-up to the English pillar expansion (#5003). Regenerate the localized
bodyHtml for all ten rendered non-English locales (zh, ja, ko, de, fr, ru, es,
pt-br, it, tr) to match the expanded ~1,860-word English body — including the
new "When vibe design is the right call" decision section, the 7-question FAQ,
and the in-context links to the three cluster posts. Every locale now carries
the full pillar; reading time returns to a single shared 9 (the per-locale
overrides from #5003 are no longer needed now that all bodies are the same
length). Verified: ja/de/zh render 9 headings, both comparison tables, and 9-min
reading time.
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(web): add composer context sources
* fix(web): require resolved context paths
* fix(web): keep local context removal authoritative
* fix(web): preserve project reference fallbacks
* fix(web): clear linked dirs with context chips
* fix(web): preserve context dirs when changing workdir
* fix(web): promote matching context workdir
* fix(web): preserve shared context dir ownership
* fix(web): retain home context dirs in composer
* fix(web): preserve promoted context dirs on clear
* fix(web): keep linked context chips after send
* fix(web): hydrate home workspace context chips
* fix(web): stabilize workspace context submissions
* fix(web): drop stale home workspace context dirs
* fix(web): fail missing workspace context dirs
* fix(web): keep home workspace context visible
* feat(web): implement project directory materialization for references
- Added `ensureReferencedProjectDir` function to create a managed project's folder if it doesn't exist, ensuring that references to new projects resolve correctly.
- Updated `getProjectDetail` to include an option for directory materialization, preventing errors when referencing uninitialized projects.
- Enhanced `ProjectReferenceModal` to filter out external projects with missing directories, improving user experience.
- Introduced tests for the new functionality to ensure proper behavior when referencing projects.
This change stabilizes project referencing and enhances the overall workflow for users dealing with managed projects.
* fix reference context fail-fast paths
* feat(landing-page): strengthen the vibe-design pillar + wire hub-and-spoke links
The 4 vibe-design blog posts were splitting the bare "vibe design" query
across each other (GSC: 3 pages clustered at pos 5-6 in the same locale),
and the pillar (what-is-vibe-design) under-competed the top-ranking guides
(Visily ~2,200 words + FAQ + decision matrix; Cerence ~2,100).
Upgrade what-is-vibe-design into a proper pillar:
- Add a "When vibe design is the right call — and when it isn't" decision
section and a 7-question FAQ (PAA / featured-snippet surface), taking the
body from ~1,150 to ~1,860 words.
- Complete the hub-and-spoke: the pillar now links out to all three cluster
posts (vibe-design-tools, vibe-design-vs-vibe-coding, vibe-design-with-stitch)
in-context, consolidating topical authority on the pillar and clarifying to
search engines which page owns the head term.
- Sharpen the differentiator competitors miss — prompt to shipped code,
open-source, agent-native — since Visily stops at a mockup and Cerence is an
interview.
Follow-up: re-translate the localized bodyHtml (keep-11 locales) to match.
Locale pages keep their prior full translation until then (not broken, just
one version behind).
* fix(landing-page): keep vibe-design readingTime aligned with translated bodies
readingTime is a shared field the blog template renders for every locale.
Since this PR intentionally leaves the localized bodyHtml on the shorter
prior copy until the translation follow-up, keep readingTime at 6 so the
10 localized pages stay accurate; it moves to 9 in the localization PR when
every body grows to match the expanded English article.
* feat(landing-page): per-locale blog readingTime override
A shared readingTime can't be right for both the expanded English body and
the localized bodyHtml still on the shorter prior translation (reviewer:
9 overstates the localized pages, 6 understates English). Add an optional
per-locale readingTime to the blog i18n schema, render it in [slug].astro
when present, set the English body to 9, and pin the ten rendered locales
to 6 until the localization follow-up grows their bodies. Verified: EN shows
9 min, ja/de/es show 6.
* fix(landing-page): use per-locale readingTime on the blog index too
The detail page honored the per-locale readingTime override, but the blog
index (and its /[locale]/ wrapper) still rendered the shared English value
on both the featured and regular cards. Apply the same locale-aware lookup
there so non-English index cards match their article. Verified: EN index
card shows 9 min, JA shows 6.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* Keep AMR settings card actions inline
* Keep AMR plan badge outside clipped benefits
* Move AMR plan badge to account row
* Prevent AMR benefit badges from clipping
* Remove lower cost AMR badge
* Rename AMR console action to manage
* Carry over logo preview and AMR manage fixes
PR #4987 tightened the homepage lazy-load margin (1500px -> 600px), so the
below-the-fold about-section paintings now swap in as the user scrolls to
them instead of being pre-loaded a full screen early. That exposed a latent
bug: `.about-panel-img img` was `width:100%; height:auto` with no reserved
ratio, so between the 1×1 placeholder and the decoded webp the box rendered
as a full-width 1:1 SQUARE (~320px too tall, showing the browser's
broken-image/alt glyph and overlapping the caption) before snapping to the
real ratio.
Reserve `aspect-ratio: 1768 / 1144` (the paintings' real dimensions) plus a
faint skeleton fill. The box is correct from first paint: a clean skeleton
while the webp streams, then zero layout shift when it lands.
Verified on a throttled connection: loading box is 900×582 (was 900×900),
CLS shift 0px, and the painting fills the box exactly on decode.
Batch 3 of the /solutions/ tool-page family (SEMrush-picked), built from
the same template as batches 1-2:
- /solutions/screenshot-to-code/ targets the "screenshot to code" intent
— drop in an image of any UI and the agent rebuilds it as clean,
component-based code. Distinct input modality from design-to-code and
figma-to-code.
- /solutions/ai-prototype-generator/ targets "ai prototype generator"
(Commercial intent, competitor long-tails vs Figma/Cursor/Penpot).
Deliberately differentiated from the existing /solutions/prototype/
use-case page: distinct H1 ("The AI prototype generator that ships
code" vs "Prototype at the speed of a prompt"), generator/tool framing,
competitor comparison, and the two pages cross-link so Google reads them
as complementary rather than duplicate.
Both reuse the .solution-page layout, ship a warm-paper hero
illustration, join the Solution dropdown + hub Tools group (now seven
generators), cross-link the cluster, breadcrumb under the /solutions/
hub, and are localized to all keep-11 locales (en/zh first-party, the
other nine Agent-translated).
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* perf(landing): load matter-js + cobe on demand, not inlined
The homepage inlined the full matter-js physics engine (~83KB) and the
cobe globe runtime (~13KB) into every document, even though both are
below-the-fold decorations. That shipped ~96KB of decorative JavaScript
in the critical HTML to every visitor — phones and reduced-motion
readers included — inflating the document the browser must download and
parse before the page settles.
Vendor both runtimes to public/enhancers/*.js (regenerated from
node_modules on every build/dev, so they always match the installed
versions) and inject each one via IntersectionObserver only when its
section nears the viewport. Reduced-motion readers skip the matter-js
download entirely and just get the server-rendered banner.
The site still ships zero Astro-bundled / ES-module JavaScript — these
are hand-vendored classic scripts injected by a runtime-created script
element, so the `Verify zero external JavaScript` gate stays green.
Homepage document: 358KB -> 264KB (brotli wire 94KB -> 51KB); the two
runtimes now load lazily, cached immutably per versioned URL.
* perf(landing): defer below-the-fold homepage art off the LCP path
The Cloudflare RUM network trace showed homepage LCP (~2.4s, the hero
webp) was starved of bandwidth: ~1.9MB of images — most of it below the
fold — was fetched in the first ~700ms and competed with the hero for
the connection. Culprits: two full-bleed section backdrops loaded via
CSS `::before` (lab-stage-art 454KB, cta-bg 335KB), the Labs dock
preloading ~500KB of preview stills on init, the contributor orbit
building ~350KB of avatars on init, and a few raw eager <img>.
Defer all of it until its section nears the viewport:
- precise-lazyload gains a `data-precise-bg` mode (adds `.precise-bg-in`,
which the CSS uses to gate the `::before` background-image — you can't
set a pseudo-element's background from JS) and a configurable
`imgRootMargin`. The homepage mounts it at 600px instead of the catalog
default 1500px so its heavy art doesn't join the initial burst.
- A shared `__whenNear(selector, cb)` helper gates the Labs dock
(`enhanceLabSwitch`) and contributor orbit (`enhanceContributorOrbit`)
init behind an IntersectionObserver.
- `cta-window` gets `loading="lazy"`; the near-fold hero product shot gets
`fetchpriority="low"` so the hero-bg (the LCP element) wins the pipe.
Verified in a headless browser against the built site: initial requests
drop 50 -> 20, the ~1.76MB of below-fold art is withheld until scrolled
to (then loads on cue), CLS stays 0.001, and every enhancer still works
(section backdrops paint, Labs dock switches, falling-text physics runs
23/23, globe renders, 16 contributor avatars build).
* perf(landing): shrink oversized homepage backdrops to display size
The two full-bleed section backdrops shipped far more pixels than they
ever render: cta-bg was 2776×1554 (335KB) and lab-stage-art 2262×1358
(454KB), but both display at roughly 960px CSS — 1920px covers even a 2×
retina panel. Re-encoded at 1920px wide, q82 webp:
cta-bg.webp 335KB → 174KB (-48%)
lab-stage-art.webp 454KB → 276KB (-39%)
~340KB saved with no visible quality loss (verified at 2× device scale —
the painterly murals stay crisp). Only the pixel dimensions dropped; the
quality factor is high. The homepage's gated `background-image` URLs bump
their `?v=` so the immutable edge cache serves the new files immediately.
* perf(landing): redirect locale from <head> so the wrong-locale first load aborts
A non-English visitor hitting the English root ran the locale
auto-redirect from a <script> late in <body>, so the browser had already
streamed most of the document (and kicked off its head resources) before
bouncing to /zh/ etc. — a wasted near-full first load.
Move the auto-redirect decision to the top of <head> (first thing after
the viewport/theme-color meta) so it fires as the document starts
streaming and aborts the rest of the wrong-locale load. The switcher UI
wiring, which needs the DOM, now defers itself to DOMContentLoaded, so it
works whether the script runs in <head> (homepage) or late in <body>
(other layouts). All existing guards are untouched — canonical-only pages,
autoredirect-off pages, and already-localized roots still no-op, so
English and crawler traffic pays only a tiny inline read.
Verified: root / still redirects to /zh/ for a zh browser with no loop,
and all 11 language-switcher links bind correctly post-DOMContentLoaded.
* feat(landing): add AMR sign-in header
* feat(landing): center sign-in popup, scrim the page, return home after login
Improve the AMR sign-in popup flow on the landing header:
- Center the vela login popup over the current window (multi-monitor aware)
instead of letting the browser place it arbitrarily.
- Dim the page with a focus scrim while the popup is open so it reads as a
modal step; remove it on success, cancel, or timeout.
- After a successful login, close the popup and return the main window to the
localized Open Design homepage (in place when already there).
- Fall back to a same-tab navigation when the popup is blocked.
Applied to both the sub-page enhancer (header-enhancer.astro) and the
homepage's inlined copy (index.astro).
* fix(landing): normalize AMR home redirect
---------
Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>
* feat(daemon): add 'plan' session mode and update related functionality
- Introduced a new session mode 'plan' alongside existing 'design' and 'chat' modes, allowing for editable document creation.
- Updated various functions and interfaces to accommodate the new session mode, including normalization and usage in commands.
- Enhanced markdown rendering capabilities by integrating micromark and its GFM extension for improved markdown processing.
- Added new input types for question forms, expanding the range of user interactions.
- Updated UI components to reflect changes in session modes and ensure proper handling of next steps based on the current mode.
* feat(chat): integrate SessionModeToggle into ChatComposer and HomeHero
- Added SessionModeToggle component to both ChatComposer and HomeHero for improved session management.
- Updated HomeHero styles to accommodate the new mode switcher layout.
- Adjusted countdown timer in QuestionsPanel to extend the skip countdown from 120 seconds to 10 minutes, enhancing user experience.
- Added tests to ensure the countdown functionality works as expected.
* feat(FileViewer): implement synchronized scrolling for Markdown editor and preview
- Added functionality to synchronize scrolling between the Markdown editor and preview panes.
- Introduced new types and utility functions for managing scroll behavior.
- Enhanced the MarkdownViewer component to handle scroll events and maintain scroll position across different modes.
- Updated the component's state management to accommodate the new scrolling features.
* feat(excalidraw): integrate Excalidraw into the project
- Added @excalidraw/excalidraw as a dependency in package.json.
- Updated vitest configuration to include an alias for Excalidraw.
- Imported Excalidraw CSS in the layout component for styling.
- Modified AssistantMessage component to handle optional projectId.
- Enhanced FileOpsSummary to display delete operations.
- Implemented new Excalidraw scene management in SketchEditor and FileWorkspace components.
- Updated MarkdownViewer to support file mentions and improved file handling.
- Refactored various components to accommodate Excalidraw integration and ensure compatibility with existing features.
* feat(files): improve sketch and file handoff flows
* test: align post-merge expectations
* chore(nix): refresh pnpm deps hash
* fix(workspace): stabilize sketch persistence and ci checks
* fix(workspace): address review blockers in editable files
* fix(workspace): persist cleared sketch scenes
* test(workspace): type sketch editor mock scene
* fix(workspace): serialize sketch autosaves
* fix(workspace): keep sketch save revisions current
* test(e2e): stabilize project workspace smoke flows
* fix(analytics): preserve plan mode for BYOK runs
* test(e2e): stabilize new project rail interactions
* fix(files): stop bash delete parsing at shell operators
* test(e2e): stabilize ui cold-start suites
* fix(viewer): preserve absolute markdown image sources
* feat(workspace): preload sketches and enhance markdown save options
- Added functionality to preload persisted sketches before opening the tab.
- Introduced new MarkdownSaveOptions type to manage save behavior.
- Updated saveMarkdownText to handle options for refreshing files and showing saving state.
- Enhanced FileViewer to maintain focus and selection during metadata refresh.
- Implemented a Toast component for user feedback on save and export actions.
* fix(web): stabilize markdown and sketch editor polish
* fix(web): finish sketch editor merge resolution
* chore(nix): refresh pnpm deps hash
* fix(plan): bypass discovery and stabilize markdown sync
* fix(web): simplify scene retrieval in SketchEditor component
* feat(web): enhance markdown viewer with auto-save functionality
- Implemented passive auto-save status in the MarkdownViewer component, replacing the manual Save button with an auto-save indicator.
- Introduced new hooks and state management for tracking auto-save events and displaying the last saved time.
- Added support for synchronized scrolling between the markdown editor and preview.
- Created a new markdown-scroll-sync module to handle scroll synchronization logic.
- Updated localization files to include new strings for auto-save messages.
- Added a SketchEnginePrewarm component to optimize Excalidraw loading times.
* feat(web): enhance session mode toggle with cost indicators
- Added cost tiers for each session mode in the SessionModeToggle component, providing users with a visual representation of usage costs.
- Introduced a new ModeCostTag component to display cost information alongside session mode labels.
- Updated localization files to include new keys for cost labels and notes.
- Enhanced styling for cost indicators to improve user experience and clarity.
- Refactored EntryShell to open the new project modal instead of creating a blank project directly from the rail.
- Implemented a utility function in markdown-scroll-sync to check for vertical progression in block offsets.
* feat(web): add max height adjustment for session mode description card
- Introduced maxHeight prop to the ModeDescriptionCard component to control the height of the description card based on available space.
- Implemented useLayoutEffect in SessionModeToggle to dynamically calculate and set the maximum height of the description card, ensuring it does not overlap with the project tab bar.
- Updated tests to verify that session modes display their expected usage/cost correctly in the UI.
- Enhanced localization files to include new cost-related strings for various languages.
* feat(web): implement goBack function for improved navigation and update auto-open logic
- Added a new `goBack` function to handle in-app navigation, allowing users to return to the previous route instead of a hardcoded destination.
- Updated the `navigate` function to maintain history state for better back navigation.
- Refactored auto-open logic to prioritize produced artifacts, allowing markdown files to be opened alongside HTML files.
- Updated tests to cover new navigation behavior and artifact selection logic.
- Enhanced localization files to include new descriptions for workspace actions.
* refactor(web): remove create design system functionality and update design files panel actions
- Removed the `onCreateDesignSystem` prop and associated button from the DesignFilesPanel component.
- Updated the empty state actions to include a button for creating a new document via the `onPaste` function.
- Adjusted tests to reflect the removal of the design system creation action and ensure the new document button is functional.
- Enhanced the MarkdownViewer component by adding a placeholder for the text area and removing the header bar for a cleaner interface.
- Updated localization files to include a new placeholder string for the markdown editor.
* fix(web): restore markdown placeholder translations
* refactor(web): streamline MarkdownViewer and enhance localization
- Removed unnecessary state management and reload functionality from the MarkdownViewer component for improved performance.
- Added a placeholder text for the markdown editor in multiple localization files to enhance user guidance.
- Updated styles for the save state indicator in the viewer to improve visual clarity and alignment.
- Adjusted tests to reflect changes in the MarkdownViewer and ensure proper functionality.
* fix(web): adjust SketchEditor button size and remove shortcut hints
- Reduced the icon size in the SketchEditor component from 13 to 12 for better alignment.
- Updated the removeSketchMermaidShortcutHints function to also remove the submit shortcut hints from the dialog, enhancing the user interface by decluttering unnecessary elements.
- Adjusted tests to verify the absence of shortcut hints in the modal after updates.
* fix(web): address plan mode follow-up polish
* fix(web): align ci expectations after merge
* test(e2e): stabilize project workspace helpers
* test(e2e): scale settings visual timeout
* fix(prompts): lock ElevenLabs voice picker choices
* test(e2e): pin project workspace P0 worker
* test(e2e): use rail new project entry
* test(e2e): relax app restoration startup waits
* fix(web): limit markdown pipe escaping to tables
---------
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
Co-authored-by: Amy <1184569493@qq.com>
Batch 2 of the /solutions/ai-<x>-generator/ tool-page family, built from
the same template as batch 1 (breadcrumb under the /solutions/ hub,
single-sourced dropdown labels, related-tools matrix):
- /solutions/ai-landing-page-generator/ targets the "ai landing page
generator" intent — prompt to a real, responsive landing page, then
shipped code.
- /solutions/figma-to-code/ targets "figma to code" with a Claude-native
angle: pull frames through the Figma MCP so Claude Code / Codex read the
design directly and generate component-based code, no locked-in export.
Both reuse the .solution-page layout, ship a warm-paper hero
illustration, join the Solution dropdown + /solutions hub Tools group,
cross-link the generator cluster, and are localized to all keep-11
locales (en/zh first-party, ja/ko/de/fr/ru/es/pt-br/it/tr
Agent-translated).
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
The settings popover already linked X, Threads, and YouTube; add the three
remaining official Open Design accounts (Instagram, LinkedIn, Xiaohongshu)
as follow rows, and add matching rotating "useful info" tips in the design
files panel so each account is surfaced there too.
New i18n keys are fully localized across all 19 locales, and the
settings_popover analytics `element` union gains follow_instagram /
follow_linkedin / follow_xiaohongshu.
Co-authored-by: Tuolalala <xinglige0205@gmail.com>
* feat(landing-page): upgrade 5 tutorials to long-form guides with distinct real screenshots (batch 6)
Batch 6, five angles:
- dylan-michael: Open Design for agencies (Apache-2.0 commercial safety + cost-managed model switching)
- ai-fire-academy: restyle without rebuilding (iterate visual identity on the same content)
- ai-fusion: the four content libraries (skills, systems, templates, and the auto-enforced craft layer)
- nyndra: a developer's under-the-hood look (deterministic loop + architecture + BYOK proxy)
- tony-xhepa: which coding agent to run it with (13+ supported, how to pick)
Each tutorial gets three distinct real in-app screenshots (no two share the same set).
* feat(landing-page): localize batch 6 long-form tutorials to the keep-11 locales
Agent-translated long-form bodies for the 5 batch-6 tutorials into the keep-11 non-English locales. Tag + image-src parity validated per locale. Per-article shards; index now 31 articles.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(landing-page): add AI wireframe generator tool page
First of the /solutions/ai-X-generator tool-page family (SEO action plan
P0-3; Pixelcut/Figma tool-SEO model adapted to OD). Targets the
'ai wireframe generator' cluster (480/KD38 + best ai wireframe generator
2026 590/KD8). Reuses the .solution-page layout + the real prototype-category
plugin grid; hero is a public-path od-site-illustration (prompt -> wireframe
-> shipped UI). New 'aiWireframeGenerator' SolutionPageKey with en + zh copy
(SolutionLocaleCopy is Partial, so other locales fall back to English).
Honest positioning: OD takes the wireframe to shipped code you own, not a
throwaway image. astro check 0 errors.
Nav dropdown entry deferred (positional label-tuple coupling) — page is
reachable via sitemap + internal/related-tools links for now.
* fix(landing-page): replace misleading plugin grid with text feature cards on wireframe tool page
* feat(landing-page): localize related-tools matrix on wireframe tool page
Move the cross-link matrix from a hardcoded English list into
solution-pages-i18n (en + zh, optional related/relatedTitle fields) so
the labels localize like the rest of the page and sibling generator
pages can extend the list as they ship.
* feat(landing-page): add AI UI generator + design-to-code tool pages
Extend the /solutions/ai-<x>-generator/ tool-page family with two more
SEO tool pages built from the wireframe-generator template:
- /solutions/ai-ui-generator/ targets the "ai ui generator" intent —
prompt to a real, component-based UI, then shipped code.
- /solutions/design-to-code/ targets the "design to code" / "ai design
to code" intent, keyword-mapped against the /blog/design-to-code-tools
listicle (blog owns "best ... tools", the tool page owns the tool
intent).
Each reuses the .solution-page layout, ships en + zh first-party copy
(other locales fall back to English), a warm-paper hero illustration, and
a localized related-tools matrix that cross-links the three generators so
they form an interlinked cluster. Follow-up: surface the Tools group in
the /solutions hub and the header dropdown (all-locale CommonCopy keys).
* feat(landing-page): surface AI generator tool pages in solutions nav + hub
Add a Tools group to the Solution dropdown and the /solutions hub so the
three generator pages (AI wireframe / AI UI / design-to-code) have real
inbound links from sitewide navigation, not just sitemap + cross-links.
- HeaderProductMenuCopy gains a tools label + a toolItems tuple,
translated across all 18 landing locales (fixed-length tuple keeps
missing translations visible at typecheck time).
- Header dropdown renders Tools as the first group, ahead of Use cases
and Roles.
- The /solutions hub renders a matching Tools section, sourcing its
heading from the product-menu copy and feeding the cards into the
CollectionPage ItemList JSON-LD.
* feat(landing-page): localize the three tool pages to the keep-11 locales
The AI wireframe / AI UI / design-to-code tool pages shipped with en + zh
body copy and fell back to English for the other rendered locales, which
read as half-translated next to the fully-localized site chrome. Add
full, Agent-translated body copy for the remaining keep-11 locales (ja,
ko, de, fr, ru, es, pt-br, it, tr), matching each locale's existing
solution-page terminology and tone. hrefs/thumbs and proper nouns are
preserved verbatim.
* fix(landing-page): single-source tool dropdown labels from solution-page copy
The Solution dropdown read tool names from HeaderProductMenuCopy.toolItems
while the hub cards read them from the solution-page breadcrumb, and the
two had already drifted in Japanese (per review). Drop toolItems entirely
and derive the dropdown labels from getSolutionPageCopy(locale, key).breadcrumb
so the nav and the hub share one translation source and cannot diverge.
* fix(landing-page): breadcrumb the tool pages under the /solutions/ hub
This PR wires /solutions/ into the header dropdown and hub cards as a real
parent for the three generator pages, but the leaf breadcrumbs and their
BreadcrumbList schema still flattened to Open Design -> <page>. Insert a
localized /solutions/ middle item in both the rendered <nav> and the
JSON-LD on all three tool pages so the trail matches the navigable
hierarchy. Label comes from header.nav.solution (already localized).
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>