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>
Colleagues have been opening PRs straight into release/vX.Y.Z (e.g. into
release/v0.13.0), bypassing main + the backport flow. Add a guard workflow:
on a PR opened/reopened/edited with a release/** base, if the author is not a
release-automation bot (open-design-release-bot, github-actions), post a comment
explaining the backport flow (merge to main, add `backport release/vX.Y.Z`) and
close the PR.
Closing (not a failing check) is the only real gate here: release/* branches
have no required status checks and no merge queue, so a red check would not
block a merge.
Co-authored-by: lefarcen <ontf116@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>
* feat(landing-page): upgrade 5 tutorials to long-form guides with distinct real screenshots (batch 5)
Batch 5, five distinct non-cannibalizing angles:
- ai-teaches-better: the 6-layer anti-slop quality engine
- compile-future: turn a reference image (Dribbble shot) into a real page, free via Gemini
- justyn: same-prompt head-to-head vs Claude Design + multi-variation
- eli-rigobeli: make slide decks from a video/article, on free credits (title rewritten from Portuguese)
- better-stack: why even a budget model designs well (design systems + skills carry it)
Each tutorial gets three distinct, angle-relevant real in-app screenshots (no two share the same set).
* feat(landing-page): localize batch 5 long-form tutorials to the keep-11 locales
Agent-translated long-form bodies for the 5 batch-5 tutorials into the keep-11 non-English locales (zh, ja, ko, de, fr, ru, es, pt-br, it, tr). Tag + image-src parity validated per locale. Per-article shards; index now 26 articles.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(brand-extraction): enhance programmatic extraction with reconciliation and UI improvements
- Introduced `reconcileProgrammaticExtractionTranscript` to manage the state of brand extraction transcripts, ensuring accurate status updates during extraction processes.
- Updated the `cancel-extraction` route to handle asynchronous operations, allowing for better user feedback and immediate reconciliation of extraction states.
- Enhanced the `startBrandExtraction` function to support draft design system creation, ensuring that users can see their systems immediately, even if extraction fails or is stopped.
- Improved error handling and logging for reconciliation processes, providing clearer insights into failures during brand extraction.
- Added tests to validate the new reconciliation logic and ensure that the extraction process behaves as expected under various scenarios.
These changes improve the overall user experience by providing more robust handling of brand extraction states and enhancing the visibility of the extraction process.
* feat(brand-extraction): enhance brand preview rendering and UI feedback
- Added functionality to render brand previews into projects when a draft is stopped, improving user experience by providing immediate visual feedback.
- Updated the `startBrandExtraction` function to include metadata for design system IDs and statuses, ensuring accurate tracking of brand extraction states.
- Enhanced the `renderBrandPreviewIntoProject` function to support new status types, including 'draft', allowing for better representation of brand states.
- Introduced new localization strings for draft-related messages, improving clarity for users during the brand extraction process.
- Added tests to validate the new preview rendering and status handling, ensuring robustness in the brand extraction workflow.
These changes improve the overall user experience by providing clearer feedback and enhancing the visibility of brand extraction processes.
* feat(design-kit): browse design-system images in a lightbox carousel
The image-preview lightbox showed a single static image with no way to move
between samples. Replace the single-image state with an index into the
visible, non-broken samples so the modal becomes a carousel: prev/next
chevrons, an "N / total" counter, ArrowLeft/ArrowRight keys, and wrap-around.
Broken tiles are filtered once through a shared lightboxItems memo so the
gallery and lightbox indices stay aligned with the delete handler.
* feat(brands): reveal the draft design system the moment extraction starts
A brand extraction pre-creates a draft `user:` design system, but the project
view only rendered it once the registry summary had refreshed, leaving the
Design System tab empty for the whole extraction. Build a fallback summary
from project metadata so the draft renders immediately, auto-open the Design
System tab when extraction begins or is cancelled, and hydrate the freshly
created project with its brand metadata. Draft pre-create now records the
source URL in provenance and fails loudly instead of swallowing the error.
Because ProjectView imports DESIGN_SYSTEM_TAB at module scope, every
FileWorkspace test mock must export the constant.
* fix(design-system-picker): restore fullscreen preview styles dropped in routines.css reorg
The brand-extraction routines.css reorganization accidentally removed the
`.project-ds-picker-fullscreen` rule block, its `project-ds-picker-fullscreen-in`
keyframes, and its responsive overrides. The modal-window drag guard and two
style specs still depend on those rules (the fullscreen design-system preview
must stay above modal chrome), so they went red. Restore the block verbatim to
match main.
* feat(brand-extraction): add continue extraction functionality for incomplete brands
- Introduced a new API endpoint to restart the deterministic programmatic extraction for existing brands without creating duplicates.
- Implemented a tracking mechanism for ongoing extractions to manage their state effectively.
- Enhanced the UI components to support the new continue extraction action, including loading states and callbacks.
- Updated relevant tests to ensure the new functionality works as expected and integrates smoothly with existing workflows.
These changes improve the user experience by allowing users to resume brand extractions seamlessly, enhancing the overall efficiency of the brand management process.
* feat(skills): integrate skill management into the application
- Added a new SkillDetailsModal component to display detailed information about skills.
- Enhanced the ChatComposer and HomeHero components to support skill selection and details viewing.
- Updated the ComposerPlusMenu to include a skills submenu, allowing users to search and pick skills.
- Implemented functionality to handle skill details in various components, improving user interaction with skills.
- Refactored existing components to accommodate skill-related features, ensuring a cohesive user experience.
These changes enhance the application's capabilities by providing users with better access to skill information and management, streamlining workflows involving skills.
* feat(brand-extraction): improve brand assistant message handling and UI feedback
- Enhanced the AssistantMessage component to better manage events and display content, ensuring that messages are rendered correctly based on their content and events.
- Updated the ChatPane component to hide empty brand assistant messages and improve the visibility of relevant content, enhancing user experience during brand extraction processes.
- Introduced new utility functions to determine the visibility of brand assistant events and content, streamlining the logic for displaying messages.
- Refactored the ProjectView component to handle brand browser assist confirmations more effectively, ensuring that the UI responds appropriately to user interactions.
- Added tests to validate the new message handling logic and ensure that brand extraction messages are displayed correctly.
These changes enhance the overall user experience by providing clearer feedback and improving the management of brand assistant messages during extraction workflows.
* fix(brands): address browser assist review blockers
* fix(web): restore new project modal entrypoints
* fix(web): switch to replacement brand retry conversations
* fix(web): restore skill-change preview invalidation
* fix(brand): harden retry completion flow
* fix(brand): close extraction lifecycle races
* test(e2e): wait for privacy banner dismissal
* fix(brand): guard retry startup races
* fix(brand): isolate extraction retry attempts
* fix(design-systems): clean up partial draft creation
* fix(brands): let stop supersede stalled transcript
* fix(brands): fail thin browser html retries
* fix(brands): preserve stopped html retries
* fix(brands): reject off-path browser retries
* fix(brands): expose deterministic retry in cli
* fix(brands): serialize cancel with finalization
* fix(brands): bound cancel settlement wait
* fix(brands): bound retry takeover waits
* refactor(next-step-actions): replace titles with localized keys and update related prompts
* fix(brands): retry after browser read failures
* fix(brands): accept canonical browser redirects
* fix(brands): reset retry assist stall timer
* test(web): align picker compact preview assertions
* fix(brands): harden design kit cleanup paths
* test(e2e): stabilize AMR runtime recovery checks
* feat(brands): enhance brand extraction from post-wall pages
- Introduced `browserHarvestIsUnusable` function to determine if a harvested page lacks usable brand signals, allowing for more permissive extraction from content-rich pages that may embed anti-bot widgets.
- Updated `extractBrandFromHtml` to utilize the new function, ensuring that valid post-wall pages are processed correctly.
- Enhanced `isChallengePage` to differentiate between genuine content-rich pages and bot protection interstitials, improving the accuracy of brand extraction.
- Added tests to validate the new behavior, ensuring that pages with minimal color palettes or embedded widgets are handled appropriately.
* feat(brands): improve handling of recoverable extraction states
- Refactored brand extraction logic to maintain a `needs_input` status for recoverable scenarios, such as blocked pages or mid-load content, instead of marking them as `failed`.
- Updated related functions and routes to reflect this change, ensuring that the user interface presents a calm, retryable state rather than a terminal failure.
- Enhanced tests to validate the new behavior, confirming that the system correctly identifies and manages recoverable extraction attempts.
* feat(projects): add design-system project creation from existing projects
- Implemented a new command `od project create-design-system` to duplicate a regular project as a design-system workspace, including a prompt for design-system generation.
- Enhanced the API to support the creation of design-system projects, ensuring proper metadata and file copying from the source project.
- Added a detailed prompt structure for the design-system generation process, outlining requirements and expected outputs.
- Introduced tests to validate the new functionality, ensuring that design-system projects are created correctly with the appropriate context and files.
- Updated the UI components to integrate the new design-system creation functionality, allowing users to initiate the process seamlessly.
* feat(projects): add project duplication workflow
* fix(brand): keep browser assist recovery retryable
* fix(plugins): roll back failed template duplicates
* feat(brand): enhance browser assist functionality and improve user guidance
- Introduced a new `brandBrowserAssistOdCard` function to generate browser assist cards for better user interaction.
- Updated the content structure in `reconcileProgrammaticExtractionTranscript` to include browser assist cards when applicable.
- Enhanced user guidance in error messages for stalled and stopped extraction processes, providing clearer instructions for recovery actions.
- Added tests to ensure the new browser assist card functionality is correctly integrated and displayed in the chat interface.
- Improved localization for various user prompts and messages related to browser assist actions.
* feat(design-browser): enhance design file handling and user notifications
- Added support for opening design files directly from the status message in the DesignBrowserPanel.
- Introduced a new `actionTarget` property to differentiate between design files and regular files in status messages.
- Implemented a `stopLoading` function to halt page loading when necessary, improving user experience during snapshot captures.
- Updated localization files to include new status messages and project type labels.
- Enhanced toast notifications for browser snapshots with improved styling and functionality.
- Added tests to ensure new features work as expected and do not interfere with existing functionality.
* feat(app): implement design system project creation with preset prompts
- Updated project creation logic to route through the default design router, ensuring user interaction prompts for design system selection.
- Introduced a new localization key for the design system creation prompt, enhancing user guidance.
- Adjusted plugin ID to avoid assumptions about prototypes, improving the flexibility of project creation.
- Updated tests to reflect changes in project creation behavior and ensure correct routing and prompt handling.
* feat(chat): update icon sizes and implement draft persistence in HomeView
- Increased icon sizes in ChatComposer from 13px to 16px for better visibility.
- Added localStorage persistence for the Home composer prompt and design system selection to retain user input across tab switches.
- Implemented functions to read and write drafts to localStorage, ensuring a seamless user experience.
- Cleared drafts upon run creation to prevent reappearance of previous inputs.
- Enhanced Toast component to handle auto-dismissal correctly, even with changing parent components.
* fix(pr): address review blockers
* fix(web): preserve authoring prompt confirmation
* test(daemon): cover project CLI copy commands
* fix(web): surface skill detail load failures
The Feishu release card (notify-release-feishu.yml) builds its changelog as
`git log <previous>..<current>`, reading <previous> from the published
prerelease/latest/metadata.json `.github.commit`. That field is written by
githubInfo(), which reads the RELEASE_COMMIT env. release-beta sets
RELEASE_COMMIT on every build + publish job; release-prerelease set it on none,
so every prerelease published an empty github.commit. Each prerelease then
found no baseline and the card always rendered "首个 Prerelease 包,无上个版本可
对比" — the changelog was permanently empty, not just for a fresh release line.
Add RELEASE_COMMIT to the four prerelease build jobs and the publish job,
mirroring release-beta. Both are required: publish-metadata rejects a
per-platform manifest whose github.commit disagrees with the metadata commit,
so the build jobs (which write per-platform manifests) and the publish job
(which writes the final metadata.json) must stamp the same built commit.
Red spec in packaged-smoke-workflow.test.ts asserts each prerelease build +
publish job carries RELEASE_COMMIT (red on main, green here).
The first-call and aggregate cache-hit ratios assumed every `openai` usage
source folds the cache-read subset into `input_tokens` (cached ⊆ input). That
holds for OpenAI chat-completions and codex's rollout, but the Responses-API /
ACP usage the AMR/vela and pi streams emit reports `input_tokens` as the
UNCACHED remainder with cache-read tokens reported separately on top, so
cache_read > input. Dividing cache_read by that too-small denominator pushed
cache_hit_ratio and first_call_cache_hit_ratio far above 1.0 (~78% of AMR and
~57% of pi follow-up run_finished events) and collapsed uncached_input_tokens
to 0.
Resolve effective-input through one shared helper that detects the additive
shape from a hard arithmetic invariant — a cache-read subset can never exceed
the total it is a subset of, so cache_read > input proves the payload is
additive — and folds cache-read/creation into the denominator (anthropic
semantics). Every cache_read <= input payload stays byte-identical; only the
previously-corrupt additive case is repaired.
Red spec asserts the AMR-shaped additive event yields ratio <= 1 (was 4.7) and
uncached == input (was 0), plus an inclusive-OpenAI guard so codex/openai do
not regress.
* feat(landing-page): upgrade 5 tutorials to long-form guides with distinct real screenshots (batch 4)
Batch 4 converts five thin tutorial entries into original long-form guides,
each from a distinct, non-cannibalizing angle:
- iishny: an honest first look (bugs, fixes, wiring any model via OpenRouter)
- 01coder: from prompt to live URL — edit, inspect, one-click deploy (Vercel/Cloudflare)
- panda: five end-to-end workflows that chain skills into real pipelines
- chase: Open Design's open-source lineage and where it fits in the OSS toolbox
- where-do-i-click: the absolute-beginner guide — install on your PC, build your first page
Each tutorial gets three distinct, angle-relevant real in-app screenshots (no
two tutorials share the same set), reusing the captured Open Design app shots.
* feat(landing-page): localize batch 4 long-form tutorials to the keep-11 locales
Agent-translated long-form bodies for the 5 batch-4 tutorials into the keep-11
non-English locales (zh, ja, ko, de, fr, ru, es, pt-br, it, tr). Each preserves
the English HTML structure exactly (validate-i18n.py: tag + image-src parity).
One per-article shard each under app/_data/tutorials-longform/; index now 21 articles.
* fix(landing-page): strip trailing whitespace in where-do-i-click tutorial
* fix(landing-page): make localized intros language-neutral (drop 'rewritten in English')
For the two non-English-source tutorials (first-look-community, 01coder), the
localized long-form intros translated the English-source clause 'rewritten in
English', so non-English readers saw a page in their language claiming it was
rewritten in English. Replace the localized intro paragraph with a
language-neutral phrasing in each of the keep-11 non-English locales; the English
Markdown source is unchanged. Addresses Looper's non-blocking review note on #4941.
---------
Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
* feat(landing-page): add localized /pricing/ page synced with the cloud subscription modal
Adds a Pricing entry to the top nav and a new /pricing/ page that mirrors the
Open Design Cloud (vela) subscription modal: three-tier plan cards (Plus/Pro/Max)
with the plan wordmark logos, monthly/yearly toggle, first-month / yearly-discount
pricing, model-credit and design-task metrics, the customer story, the FAQ, and the
Team/enterprise banner.
- Plan numbers come from a baked snapshot and are reconciled at runtime from the
cloud's published plans.json, so a price change in the cloud reflects here with
no landing-page rebuild.
- All visible copy is localized for en/zh/zh-tw/ja/ko/de/fr/ru/es/pt-br (mirrored
from the cloud), with English fallback for other locales; the nav label is
translated across all landing locales.
- Subscribe CTAs deep-link into the cloud console with the selected tier+interval
and checkout=auto, so checkout starts in the cloud (auth-gated) and returns to
the console on success.
* fix(landing-page): address pricing review feedback
---------
Co-authored-by: NJUHua <113895241+NJUHua@users.noreply.github.com>