Commit Graph
1223 Commits
Author SHA1 Message Date
439f071cb0 feat(landing-page): replicate #2469 SEO content with deploy + regression fixes (#2605)
* chore(landing-page): bring PR #2469 content wholesale onto post-revert main

Step 1 of replicating @pftom's #2469 work without the deploy-blocking
issues that forced #2603. This commit copies the full \`apps/landing-page/\`
diff from #2469's HEAD (`9d2a4f1`) onto current main verbatim — every
i18n bundle, every page rewrite, every \`[locale]/\` wrapper. Subsequent
commits on this branch then surgically restore the SEO fixes that
#2469 silently regressed and configure the sitemap to survive the
Cloudflare Pages 25 MiB limit, so deploy is healthy when this lands.

What's in this commit
- Tom's i18n bundle: \`i18n.ts\` (5377 lines), \`home-page-i18n.ts\`,
  \`info-page-i18n.ts\`, \`landing-ui-i18n.ts\`, \`content-i18n.ts\`
  (~10K lines total of locale data)
- 18 landing-page locales: en, zh, zh-tw, ja, ko, de, fr, ru, es,
  pt-br, it, vi, pl, id, nl, ar, tr, uk
- All existing pages rewritten to consume the new i18n bundle
- Full \`[locale]/<route>/\` wrapper tree for every catalog page
- \`plugin-registry.ts\` rewrite, \`catalog.ts\` adjustments
- \`astro.config.ts\` route + sitemap reconfiguration
- \`public/_headers\`, \`public/_redirects\`, \`public/favicon.svg\` adds
- \`_components/locale-switcher-script.astro\` add

What's intentionally NOT done in this commit (handled in follow-ups
on this same branch):
- Restore brand mark 44px + rounded corners (was lost from #2588)
- Restore HA SoftwareApplication \`alternateName\` array (was lost from #2566)
- Restore HA \`url\` canonical pointing at the landing page (was lost from #2586)
- Restore Product/Library/Tutorials/Blog nav grouping (was lost from #2588)
- Restore catalog-card padding 24px (was lost from #2600)
- Configure sitemap to filter \`[locale]/\` routes so the generated XML
  stays under 25 MiB and Cloudflare Pages accepts the deploy
- Add \`/zh-CN/* → /zh/*\` redirects for backwards-compatibility with
  any externally-linked OD-canonical locale URLs

Validation so far
- \`pnpm --filter @open-design/landing-page typecheck\` — 0 errors

* fix(landing-page): unblock deploy + restore SEO regressions on top of #2469

Step 2 of replicating @pftom's #2469. The previous commit on this
branch brings #2469's content wholesale; this commit applies the
surgical fixes that make the result actually deploy and preserves
the SEO improvements that #2469 silently regressed.

Fix 1 — sitemap stays under Cloudflare Pages 25 MiB upload limit
- `astro.config.ts` `filter` now drops every `/{locale}/...` route
  so the sitemap only emits canonical English URLs.
- Locale variants are still discoverable via the
  `<xhtml:link rel="alternate" hreflang="...">` annotations the
  `namespaces.xhtml: true` option emits inside each canonical entry.
  This is Google's recommended pattern for a multi-language site.
- Verified: post-fix `out/sitemap-0.xml` = 179 KB (was 38.4 MiB
  on the prior attempt that forced #2603's revert).

Fix 2 — header brand block restored to the polished version
- Logo `width/height` 36 → 44 (matches PR #2588's brand-mark refresh
  for visual weight against the new black speech-bubble glyph)
- `.brand-meta` block ("Studio Nº 01 · Berlin / Open / Earth") removed
  from the header bar; the same editorial flourish still lives on the
  rotated `.side-rail .rail-text` pseudo-elements at page edges.

Fix 3 — header nav grouped into Library + standalone Tutorials/Blog
- Skills / Systems / Templates / Craft are now children of a Library
  dropdown (matches PR #2588's grouping). Each row keeps its count
  badge inline; the trigger highlights when any of the four facet
  pages is active.
- Tutorials and Blog stay as standalone top-row items (PR #2588's
  original decision after Joey's review on the Learn dropdown).
- Contact removed from the header — it was a same-page anchor that
  the footer already surfaces.
- Hardcoded "Library" / "Tutorials" labels match the brand-name
  pattern: unlocalized across all 18 landing-page locales.

Fix 4 — HA SoftwareApplication entity canonicalized on the LP again
- `alternateName` is back to an explicit array of real query
  variants `["html anything", "html-anything", "htmlanything",
  "HTML Anything Editor", "The agentic HTML editor"]`. #2469
  re-routed it through `copy.schemaAlternateName` which dropped
  the literal alias declarations Google needs for spaced-vs-
  hyphenated-vs-joined matching. (Restores PR #2566.)
- `url` flips back from `HA_URL` (the GitHub repo) to the LP URL
  itself, matching the `BreadcrumbList` block on the same page.
  GitHub repo lives in `sameAs` as a peer surface. (Restores PR
  #2586. Without this, Google credits the GitHub repo as canonical
  for the entity, which is the opposite of what this surface
  exists for.)

Fix 5 — catalog-card horizontal padding unified at 24 px
- featured-card 22 → 24, template-card 20 → 24,
  system-card 18 → 24, source-card 28 → 24.
- For template-card, also moved horizontal padding into the group
  rule exclusively so future siblings join without re-asserting
  margin shorthands. (Restores PR #2600.)

Fix 6 — `_redirects` for the locale-code rename
- This bundle uses `zh` / `zh-tw` / `pt-br` / `es` (the codes Tom's
  i18n.ts ships). The previous OD landing-page used `zh-CN` /
  `zh-TW` / `pt-BR` / `es-ES`. Externally-indexed and inbound-linked
  URLs against the old prefixes now 301 to the new canonical.

Validation
- `pnpm --filter @open-design/landing-page typecheck` — 0 errors
- `pnpm --filter @open-design/landing-page build` — completed
  successfully; 18,204 pages built; sitemap-0.xml is 179 KB
  (well under the 25 MiB Cloudflare Pages limit).

* docs: promote 'open-source alternative to Claude Design' to README H1

Brings the missing README and .gitignore changes from #2469 that the
first wholesale-checkout in this branch missed (the auto-pulled diff
scope was filtered to apps/landing-page/ initially).

What
- Every README.*.md (13 locale variants) now leads with the
  "open-source alternative to Claude Design" tagline as a subtitle to
  the project name in the H1 / first paragraph. This was @pftom's
  brand-positioning commit (`ee851dc`) on the original #2469 branch.
- `.gitignore` adds `growth/**` to keep growth-research scratch out of
  the repo.

Why
- The README is one of the highest-PageRank surfaces a GitHub project
  exposes to Google. Promoting the "alternative to Claude Design"
  framing into the H1/subtitle position makes the project surface for
  exactly the query the SEO work in this PR is trying to capture.
- Without this commit, the replicated #2469 in this branch would still
  rank against the previous H1 ("Open Design") on GitHub crawls,
  letting the SEO win at the LP fall short on the GitHub surface.

This is a strict subset of #2469's content — pure docs, no code,
no behavior change beyond what GitHub renders on the repo overview.

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-22 00:59:11 +08:00
eefaf4504a Revert "Enhance landing page with SEO-focused content and FAQ section (#2469)" (#2603)
This reverts commit 26ee030b4c.

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-22 00:23:37 +08:00
Tom HuangandGitHub 26ee030b4c Enhance landing page with SEO-focused content and FAQ section (#2469)
* Enhance landing page with SEO-focused content and FAQ section

- Updated `.gitignore` to include growth directory.
- Modified `astro.config.ts` to prioritize high-intent landing pages for SEO.
- Added new FAQ styles and layout in `globals.css` for better user experience.
- Implemented FAQ section in `page.tsx`, ensuring it aligns with structured data requirements.
- Created dedicated pages for agents and alternatives to Claude Design, enhancing SEO and user navigation.
- Introduced comparison page for evaluating Open Design against competitors.
- Added favicon links component for consistent branding across all pages.

* Add SVG favicon and update favicon links for improved branding

* Enhance landing page with official source pillars for improved branding and navigation

- Added five canonical "official source" pillars to the homepage, reinforcing key links: official site, GitHub repository, releases, documentation, and Discord community.
- Updated URLs for releases, issues, documentation, and license to streamline access and improve user experience.

* Add locale support and enhance landing page with language switcher

- Introduced locale management with a new i18n module, defining multiple languages for the landing page.
- Implemented a locale switcher in the topbar and header, allowing users to select their preferred language.
- Updated global styles for the locale selector and adjusted layout for better responsiveness.
- Enhanced SEO by ensuring localized content is served based on user selection.
- Added a script for automatic locale detection and persistence in local storage.

* Implement localized routing and enhance navigation with href utility

- Added `stripLocaleFromPath` and `localizedHref` functions to manage locale-based URL paths.
- Updated `localePath` to normalize paths based on the detected locale.
- Refactored links in the header, footer, and main page components to utilize the new `localizedHref` function for improved navigation.
- Introduced locale-aware routing for new pages, ensuring consistent user experience across different languages.
- Enhanced SEO with alternate links for localized content in the sub-page layout.

* Update header component to use new logo format

- Replaced favicon image with a new logo in WebP format for improved performance and quality.
- Ensured consistent branding across the landing page with the updated logo.

* Enhance landing page with localization and new UI components

- Introduced a comprehensive localization schema for content management, allowing for multilingual support across various sections.
- Updated the blog and collection schemas to include internationalization (i18n) fields for better content localization.
- Implemented a new official source strip for improved navigation and branding, linking to key resources like the official site and documentation.
- Enhanced the locale switcher functionality, allowing users to select their preferred language with improved UX.
- Updated styles for the locale switcher and added new components for better responsiveness and accessibility.
- Refactored existing components to utilize localized URLs, ensuring a consistent user experience across different languages.

* Implement comprehensive localization and enhance landing page UI

- Introduced new localization features, including `EXTRA_LOCALIZED_HOME_BODY_COPY` and `EXTRA_LOCALIZED_LANDING_UI_COPY`, to support multilingual content across the landing page.
- Updated `astro.config.ts` to integrate internationalization (i18n) settings for the sitemap, improving SEO for localized content.
- Created new files for home page and info page internationalization, defining structured content for various languages.
- Enhanced the locale switcher functionality with improved UX, allowing users to easily select their preferred language.
- Refactored existing components to utilize localized content and URLs, ensuring a consistent experience across different languages.
- Made CSS adjustments for better responsiveness and accessibility in the UI components.

* Enhance landing page with new design templates and localization improvements

- Added support for design templates in the content management system, allowing for better organization and access to design resources.
- Implemented comprehensive localization for blog topics, enhancing multilingual support across various sections of the landing page.
- Updated the header component to include new product menu items, improving navigation and user experience.
- Refactored CSS for improved responsiveness and accessibility, including a new sticky chrome bar for better navigation.
- Enhanced the locale switcher functionality, ensuring a seamless experience for users selecting their preferred language.

* docs(readme): promote 'open-source alternative to Claude Design' tagline to subtitle across locales
2026-05-21 23:40:58 +08:00
e5bea2c134 feat(landing-page): SEO surfaces, schema upgrades, manifest — cherry-pick from #2469 (#2596)
Pulls the high-value, low-conflict slices of @pftom's #2469 onto
current main. That PR's branch was based on `af63af3` (May 20) and
diverged from a fast-moving main, so its Tier 1 SEO content is shipped
here as a fresh PR rather than rebased.

What's included
- **5 new SEO landing pages**, English-only for v1:
  - `/official/` — brand-authority hub naming every alias the project
    is searched as (Open Design, OpenDesign, open-design, opendesign,
    Open Design AI, OD); Organization JSON-LD with the same alternateName.
  - `/quickstart/` — three-command install path with HowTo JSON-LD,
    requirements, expected output, troubleshooting, next steps.
  - `/agents/` — 17 BYOK adapters across three tiers, ItemList JSON-LD,
    BYOK explainer.
  - `/compare/` — evaluation-stage comparison hub vs Claude Design,
    Figma Make, v0, Lovable/Bolt, Open CoDesign; mandatory honest-limits
    block as FAQPage JSON-LD.
  - `/alternatives/claude-design/` — primary commercial-intent page;
    TL;DR, why-people-search, BYOK explainer, feature-comparison table,
    who-should-pick-which, migration steps, FAQPage JSON-LD.
- **`[locale]/` wrappers** for each of the 5 new pages, generated via
  `PREFIXED_LOCALES` from OD's existing `_lib/i18n.ts`. Each wrapper is
  a thin re-export of the canonical English page; per-locale translations
  are a follow-up.
- **`seo-head.astro` schema upgrades** — `inLanguage` on Article /
  WebSite / Blog JSON-LD, `availableLanguage` on the WebSite block,
  `og:locale:alternate` for non-current locales, hreflang `x-default`
  link.
- **`favicon-links.astro` extracted as a shared component** so every
  page emits the same icon set; new sizes (favicon-16x16, favicon-32x32,
  android-chrome-192x192, android-chrome-512x512) generated from the
  current brand mark; `site.webmanifest` published for PWA / Android
  install affordances.
- **`llms.txt`** restructured to lead with brand-alias declaration and
  list every new official entry point. The Sister Projects section
  introduced in #2566 stays.

What's intentionally NOT included
- @pftom's parallel i18n bundle (`i18n.ts` / `home-page-i18n.ts` /
  `info-page-i18n.ts` / `landing-ui-i18n.ts` / `content-i18n.ts`,
  ~10K lines of locale data). It duplicates and conflicts with OD's
  existing `_lib/i18n.ts` + `_lib/home-copy.ts`. Adapting the new
  pages to OD's existing system instead keeps the codebase on a
  single source of truth; per-locale translations of the new pages
  can land as a separate PR.
- Mass-rewrites of existing pages (homepage, HA, Skills/Systems
  catalogs, blog detail). #2469's branch base predates a number of
  in-flight PRs that touched those files heavily; cherry-picking the
  rewrites would re-litigate already-merged work.
- The `[locale]/<existing-route>/` routing tree for Skills, Systems,
  Templates, etc. Without translations, mirroring 26 routes per locale
  produces duplicate-content signals; that lift belongs with a
  per-locale copy push.

Surface area
- Marketing site only. No `apps/web`, no `apps/daemon`, no contracts,
  no CLI surfaces. No new dependencies. No env vars.
- New favicon assets are static PNGs generated from the canonical
  brand-mark source via `magick`; committed as files, no pipeline.

Validation
- `pnpm --filter @open-design/landing-page typecheck` — 0 errors
- Local dev server: every new English route returns 200; every
  `[locale]/<route>/` variant (e.g. `/zh-CN/agents/`) returns 200;
  `/favicon.ico` and `/site.webmanifest` resolve.
- Local dev server: `seo-head.astro` emits the new `inLanguage`,
  `availableLanguage`, `og:locale:alternate`, and `hreflang=x-default`
  signals; `<FaviconLinks />` renders the consolidated icon set
  including the new manifest link.

Followups
- Translate the 5 new pages and replace the English-content wrappers
  under `[locale]/`.
- Swap `sub-page-layout.astro` to use `<SeoHead />` so the new schema
  upgrades reach all sub-pages, not just the homepage and any future
  pages that opt into SeoHead directly.
- Mass-update the homepage and HA page along the lines of #2469's
  rewrite, but rebased onto current main rather than off `af63af3`.

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-21 23:03:21 +08:00
netteeandGitHub 052f8097de fix(daemon): inject @-mention skills into system prompt (#2552)
* fix(daemon): inject @-mention skills into system prompt

Generated-By: looper 0.8.1 (runner=worker, agent=opencode)

* fix(daemon): compose ad-hoc skill mode and aliases

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

* fix(daemon): lazily load and stage ad-hoc skills

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

* test(daemon): assert staged skill files before spawn

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

* fix(daemon): compose skill metadata across @ mentions

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

* test(daemon): cover ad-hoc critique skill policy

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

* fix(daemon): preserve plugin skill composition

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

* fix(daemon): resolve conflicting composed skill surfaces

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

* fix(daemon): preserve primary skill surface

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

* fix(daemon): share resolved critique surface

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 22:20:21 +08:00
682a9c9a9a feat(landing-page): group header nav into Product / Library / Learn (#2588)
* feat(landing-page): group header nav into Product / Library / Learn

Reduces the top-level nav from 7 link slots (Product, Skills, Systems,
Templates, Craft, Tutorials, Blog, Contact — plus the locale switcher
and two CTAs) to 3 dropdown groups, eliminating the row-overflow
that forced the brand sub-meta to truncate at narrow desktop widths
and cramming the hamburger panel on tablet.

Why
- The four catalog pages — Skills, Systems, Templates, Craft — share
  the same shape: a list page that links into per-record details.
  They are facets of one library, not competing peer destinations.
  Letting each occupy its own top-row slot was a policy of last
  resort when there were only four; with Product newly added and
  Tutorials newly added since #2452 + #2266, the row no longer fits.
- Tutorials and Blog are both editorial reading surfaces (videos
  vs articles), so they pair naturally under one Learn group.
- Contact in the top nav was always misleading — it links to
  `#contact`, a same-page anchor on the homepage CTA section. The
  footer already lists it. Promoting it to top-row real estate while
  the row was overflowing made no sense.

What
- New `Library` dropdown holds Skills (132) / Systems (150) /
  Templates (111) / Craft (11). Each row inside the panel keeps its
  count badge inline beside the label, plus a one-line blurb so the
  panel reads as a directory rather than an undifferentiated list.
  The trigger highlights `is-active` whenever any of the four facet
  pages is the active route, so users still see "you are inside
  Library" feedback.
- New `Learn` dropdown holds Tutorials and Blog. Same pattern: inline
  blurbs, parent-highlight when either child page is active.
- `Contact` removed from the header. The footer surface still lists
  it; the top-row capacity it occupied is reclaimed.
- `.dropdown-num` CSS class added for the inline count badge inside
  dropdown rows, distinct from the existing `.num` (which floats
  above top-row links as a superscript).

Active-state semantics are preserved — every sub-page that already
passes `active="skills"`, `active="systems"`, etc. keeps working
without changes; the new Library trigger reads those same values
to decide whether to highlight itself.

Surface area
- Marketing site only. No `apps/web`, no `apps/daemon`, no contracts,
  no CLI surfaces. No new dependencies. No i18n keys (existing
  `copy.navSkills` / `copy.navSystems` / `copy.navTemplates` /
  `copy.navCraft` / `copy.navBlog` keep working; "Library" and
  "Learn" are universal English labels that don't need translation
  tables for this iteration).

Validation
- `pnpm --filter @open-design/landing-page typecheck` — 0 errors
- Local dev server at narrow breakpoints (≤1080px) — hamburger panel
  flat-expands the new Library / Learn dropdowns; existing handler
  closes the panel on link click.
- Local dev server at desktop widths (≥1180px) — top row now reads
  Product · Library · Learn, matching the design intent.

* feat(landing-page): polish brand mark — bigger glyph, single-line wordmark

Three small refinements to the header brand block, requested after
the new logo + grouped-nav landed:

1. The "Open Design" wordmark was wrapping to two lines once the new
   nav groups (Product · Library · Learn) sat alongside it on narrow
   desktop widths. The hamburger fallback already hides the entire
   nav at ≤1080px so the wordmark has plenty of horizontal room
   there — wrapping was a layout glitch, not a width constraint.
   Applies `white-space: nowrap` on `.brand` and adds an explicit
   `.brand-name` span so the rule is intent-bearing rather than
   relying on the parent inline-flex behaviour.

2. The brand mark felt undersized against the wordmark's optical
   weight, especially with the new black mark where the negative
   space inside the speech bubble visually shrinks the glyph. Bumps
   the displayed size from 36×36 to 44×44 (+22%) in both the header
   and the footer, so the proportion matches what users see in the
   logo.webp source.

3. Removes the `<span class="brand-meta">` block ("STUDIO Nº 01 ·
   BERLIN / OPEN / EARTH"). It was decorative metadata that earned a
   third of the brand block's horizontal real estate without
   carrying any user-facing function. Drops the JSX, drops the
   styles, drops the now-stale `display:none` overrides at the 1180
   and 880 breakpoints. The same rotated brand-string still lives on
   the side-rail pseudo-elements at the page edges (`.side-rail
   .rail-text`) — that surface is the canonical home for that
   editorial flourish, not the nav.

Surface area
- Marketing site only. `_components/header.tsx`, `page.tsx` (footer
  brand block), and `globals.css`. No `apps/web`, no `apps/daemon`,
  no contracts, no CLI. No new dependencies, no i18n changes.

Validation
- `pnpm --filter @open-design/landing-page typecheck` — 0 errors
- Local dev server: header HTML no longer contains `brand-meta`;
  the brand block on `/` and any sub-page renders the bigger 44px
  glyph + single-line "Open Design" wordmark.

* refactor(landing-page): unbundle Learn dropdown and round the brand mark

Two small follow-ups after looking at the rendered nav:

1. Reverts the Learn dropdown back to two standalone top-row links
   (Tutorials, Blog). Rolling exactly two items into a dropdown adds
   a click without reclaiming any horizontal space — the Library
   grouping is what genuinely cleared the row, and Tutorials + Blog
   can live side by side. Active-state semantics are preserved
   automatically since both pages already pass `active="tutorials"`
   and `active="blog"`.

2. Adds `border-radius: 10px` to the brand-mark image. The source
   PNG is a solid-fill square; clipping the corners gives the mark
   the modern app-icon silhouette (~22% of side length, matching
   the iOS / macOS convention) so it reads as a brand glyph rather
   than a raw screenshot next to the wordmark. Applies to both the
   header and footer brand blocks via the shared `.brand-mark img`
   selector.

Validation
- `pnpm --filter @open-design/landing-page typecheck` — 0 errors
- Local dev server: top row reads `Product ▾ · Library ▾ · Tutorials · Blog`
- Local dev server: brand mark renders with rounded corners on `/`
  and any sub-page (header + footer reuse the same `.brand-mark`
  styling)

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-21 21:15:48 +08:00
7631539808 Add project bulk delete feedback (#2481)
* Add project bulk delete feedback

* Restart bulk delete toast timer

---------

Co-authored-by: Ghxst <200635707+GHX5T-SOL@users.noreply.github.com>
2026-05-21 20:57:19 +08:00
0f1b74ee44 fix(landing-page): canonicalize HA SoftwareApplication on the landing page (#2586)
Follow-up to #2566. That PR introduced `url: HA_URL` plus a
two-element `sameAs` on the SoftwareApplication block, which declared
the GitHub repo as the entity's canonical surface — Google uses `url`
to decide which page to attribute structured-data entities to. The
BreadcrumbList block right below uses the landing page URL, so the
two blocks contradicted each other on what the canonical page was.

Since the goal of #2566 was making "html anything" surface the landing
page in search, canonicalizing on GitHub was an inversion of intent.
This commit switches `url` to the landing page URL and keeps
`HA_URL` only in `sameAs` so the GitHub repo is registered as a peer
reference surface, not the canonical one. The two structured-data
blocks now agree.

Surfaced by Looper (PerishCode) on the #2566 review thread; the fix
landed too late to ride the original PR, hence this small follow-up.

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-21 20:43:18 +08:00
8269b7df90 Keep live artifact preview mounted across tabs (#2482)
Co-authored-by: Ghxst <200635707+GHX5T-SOL@users.noreply.github.com>
2026-05-21 20:38:58 +08:00
c37c691d82 [codex] Add landing page Google Analytics (#2582)
* Add Claude-style design system workflow

* Merge design system workflow into main

* Restore design system workflow UI styles

* Fix design system setup scrolling

* Fix design system setup connector button

* Preserve connector auth link after popup block

* Simplify connected GitHub setup state

* Open generated design system workspace project

* Summarize design system auto prompt in chat

* Add bounded GitHub connector design intake

* Prefer path-scoped GitHub intake tools

* Restore branch GitHub design context intake

* Restore design system review workspace

* Restore design system manager tab

* Let design system workflow routes own details

* Open editable design systems as projects

* Restore design system workspace coverage

* Fix bounded GitHub connector intake

* Hide design system review while generating

* Suppress design system generation questions

* Constrain GitHub design intake to bounded command

* Tolerate oversized GitHub metadata during intake

* Rebuild daemon CLI when sources change

* Fallback when GitHub connector snapshots are rate limited

* Allow GitHub intake without Composio

* Use native GitHub auth for design intake

* Remove design system review group heading

* Improve design system extraction evidence

* Align design system scaffold with Claude output

* Add evidence inventory for design system intake

* Add local design system evidence intake

* Add design system package audit gate

* Allow auditing Claude Design reference packages

* Audit design system package content quality

* Migrate legacy design system artifacts

* Clean migrated design system artifacts

* Require modular design system UI kits

* Reject thin design system UI kits

* Prioritize core design evidence intake

* Require role-based design system UI kits

* Clean stale design system manifest references

* Require representative preserved design assets

* Warn on generic design system visuals

* Enforce design system quality warnings

* Audit connected design system UI kits

* Require mounted design system UI kits

* Require composed design system app shells

* Require runnable JSX design system kits

* Require browser globals for design system components

* Infer design system names from source URLs

* Require source examples in design system packages

* Bind preserved fonts in design system tokens

* Require skill frontmatter in design system packages

* Preserve build icons in design system packages

* Require real assets in brand previews

* Require substantive source examples

* Require product overview in design system README

* Require reusable UI kit README

* Require reusable design system skill docs

* Seed Claude-style UI kit entry contract

* Preserve runtime build assets in design packages

* Audit design system packages after generation

* Audit design system first-run output

* Audit source-backed preview cards

* Align design system UI kit scaffolds

* Materialize design evidence package artifacts

* Show project chat during design system setup

* Hand off design system setup to project chat

* Auto-repair design system audit failures

* Harden design system evidence preservation

* Tighten design system package guidance

* Add targeted design system repair guidance

* Bound design system audit auto repair

* Use connector statuses in design system setup

* Audit design system preview manifests

* Require README preview manifests for design systems

* Add landing page Google Analytics

* Keep GA PR scoped to landing page

* Cover new landing routes with Google Analytics

* Load Google Analytics without static script src

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-05-21 20:38:09 +08:00
0a5598c0e3 feat(landing-page): improve HTML Anything discoverability for SEO (#2566)
Three small additions that close the gap between users searching
"html anything" (with a space) and finding the existing
`/html-anything/` page:

1. JSON-LD `SoftwareApplication.alternateName` is now an array of
   real query variants — `html anything`, `html-anything`,
   `htmlanything`, `HTML Anything Editor`, plus the existing tagline.
   Each entry maps to a query users actually type. Feeding them as
   declared alternates is a stronger signal than relying on Google's
   tokenizer to figure out hyphen ↔ space equivalence on its own.
   Also adds a `sameAs` array linking the canonical landing page and
   the GitHub repo so structured-data crawlers see the entity span
   both surfaces.

2. `llms.txt` now lists the HA landing page in its canonical entry
   points and adds a dedicated "Sister Projects" paragraph that
   spells out the name variants and the export targets. LLM crawlers
   (Claude, Perplexity, ChatGPT browsing) read this file to decide
   what to surface; the previous version made HA invisible to them.

3. The home page footer's Library column now lists "HTML Anything"
   as a peer to Skills / Systems / Templates / Craft, which puts a
   real body-anchor link to `/html-anything/` on `/`. Nav-dropdown
   anchors (the Product menu) carry less SEO weight than an anchor
   in a discoverable content area, so this makes the home actually
   pass link equity to the sub-page. The label is hardcoded English
   intentionally — "HTML Anything" stays unlocalized as a brand name
   on every locale, so threading a new key through all 18 home-copy
   translations would just churn translators.

## Why now

The HA landing page has been live since #2452 but a "html anything"
query (the variant most users type) doesn't surface us, while the
hyphenated form does. Tokenizer equivalence isn't enough on a young
domain — we need declared signals, an inbound link from a
content-area on the highest-PR page, and machine-readable hints for
LLM crawlers. This PR ships all three.

## Test plan

- [x] `pnpm --filter @open-design/landing-page typecheck` — 0 errors
- [ ] After deploy: `curl https://open-design.ai/html-anything/`
      shows `"alternateName":[...]` array in JSON-LD
- [ ] After deploy: `curl https://open-design.ai/llms.txt` includes
      a `## Sister Projects` section
- [ ] After deploy: home page footer Library column lists HTML Anything

## Surface area

- [x] `apps/landing-page` only
- [ ] no `apps/web`, no `apps/daemon`, no contracts, no CLI
- [ ] no new dependencies
- [ ] no skill / design-system / template / craft additions

## Followups (not in this PR)

- Mirror the HA hero banner to R2 + Image Resizing (Core Web Vitals)
- Generate a HA-specific Open Graph card so social previews stay on
  brand (currently reuses the GitHub-hosted banner)
- Add a `SoftwareSourceCode` JSON-LD block to associate the landing
  page with the GitHub repository entity
- Land a Chinese landing page at `/zh-CN/html-anything/` to capture
  CN-locale queries

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-21 19:26:30 +08:00
93036afa2e Fix sketch default color in dark mode (#2488)
Co-authored-by: Ghxst <200635707+GHX5T-SOL@users.noreply.github.com>
2026-05-21 19:18:32 +08:00
Siri-RayandGitHub 3a33a7b475 fix(web): localize quick brief prompt (#2520)
* fix(web): localize quick brief prompt

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

* fix(web): pass locale from design system chat

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

* fix(web): preserve task-type routing options

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

* fix(web): preserve task-type routing options

Generated-By: looper 0.8.1 (runner=fixer, agent=codex)
2026-05-21 19:18:13 +08:00
Marc ChanandGitHub 047d2bdd95 fix(orbit): respect selected app language (#2522)
* fix(orbit): respect selected app language

Generated-By: looper 0.8.1 (runner=worker, agent=opencode)

* fix(orbit): respect selected app language

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 19:17:53 +08:00
Zellux WangandGitHub f892daae05 Polish connector detail drawer (#2528) 2026-05-21 19:17:31 +08:00
Marc ChanandGitHub 8dfcc545c7 docs(changelog): draft unreleased section (#2539)
* fix(ci): catch nix hash drift before merge

* docs(changelog): draft unreleased section

Generated-By: looper 0.8.1 (runner=worker, agent=opencode)

* docs(changelog): add missing unreleased link refs

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 19:17:17 +08:00
Weston HoughtonandGitHub ce3891f20f fix(daemon): honor hostname OD_ALLOWED_ORIGINS for no-Origin same-origin GETs (#2478)
Browsers omit the Origin header on same-origin GET requests per the Fetch
spec, but the no-Origin host-only branch in isLocalSameOrigin only honors
IP-literal entries in OD_ALLOWED_ORIGINS (via ipOnlyExtraOrigins). When a
remote-access proxy (Tailscale Serve, Caddy, etc.) terminates TLS at a
non-loopback hostname listed in OD_ALLOWED_ORIGINS, those legitimate
same-origin GETs to /api/app-config, /api/mcp/servers, etc. get rejected
with "cross-origin request rejected" 403s while the matching POST/PUTs
(which always carry Origin) succeed.

Trust Sec-Fetch-Site: same-origin as a fallback when the Origin header is
absent. The Sec-* prefix is browser-set and cannot be modified by
JavaScript, so a value of "same-origin" attests that the request really
originated from the same origin as the target — a cross-site
<img>/<script> exploit would carry "cross-site" instead, leaving the
existing CSRF defenses intact.

Tests:
- pnpm --filter @open-design/daemon test -- tests/origin-validation.test.ts → 43 passed (5 new)
2026-05-21 19:15:07 +08:00
netteeandGitHub 0108d3a655 fix(web): localize Chinese integrations copy (#2081) (#2563)
Generated-By: looper 0.8.1 (runner=worker, agent=opencode)
2026-05-21 19:07:45 +08:00
Marc ChanandGitHub fe709870ec fix(web): make PPTX export prompt availability-safe (#2546)
* fix(web): make PPTX export prompt availability-safe

Generated-By: looper 0.8.1 (runner=worker, agent=opencode)

* fix(web): restore audited PPTX export fallback

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 19:07:25 +08:00
Marc ChanandGitHub 5f20487942 test(web): cover Continue transcript regression (#2547)
* fix(ci): catch nix hash drift before merge

* test(web): cover Continue transcript regression

Generated-By: looper 0.8.1 (runner=worker, agent=opencode)
2026-05-21 19:07:07 +08:00
Nicholas-XiongandGitHub 0e6db57ac9 fix: sort automations by creation time, newest first (#2389)
- Add useMemo to sort routines by createdAt in descending order
- Replace all references to routines with sortedRoutines in render
- Newly created automations now appear at the top of the list
- Makes new items immediately discoverable after creation

Fixes #2387
2026-05-21 18:50:26 +08:00
3c1195106a fix(web): align HomeHero prompt overlay metrics (#2331)
Co-authored-by: multica-agent <github@multica.ai>
2026-05-21 18:49:07 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
8f7914f833 docs(readme): refresh contributors wall (#2148)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-21 18:35:17 +08:00
af63af3951 feat(landing-page): refresh brand mark and publish a real favicon.ico (#2561)
Replaces the four icon assets in `apps/landing-page/public/` with
renders of the new brand mark — black-fill speech bubble + white
pointer arrow — and adds a real multi-resolution `favicon.ico` at
the path SEO crawlers actually probe.

Why
- The brand mark was refreshed on 2026-05-21 (canonical source:
  black 2988×2988 PNG of the speech-bubble + pointer logo). The
  marketing site needed the matching favicon, apple-touch-icon, and
  header brand mark refreshed in lockstep so the browser tab, iOS
  home-screen tile, and the in-page nav glyph all line up with the
  new identity.
- `/favicon.ico` did not exist on the published site. The Astro head
  declares `<link rel="icon" href="/favicon.png">`, which modern
  browsers honor, but a long tail of SEO crawlers, link-preview
  services (Slack, Discord, third-party SEO tools), and older
  clients hard-probe `/favicon.ico` regardless of the link tag. Hits
  to that URL were falling through to the SPA fallback HTML
  (200 with `content-type: text/html`), so those clients rendered
  an empty/broken favicon. Several SEO surfaces showed an empty
  black circle instead of the brand mark.
- Adding a real `favicon.ico` plus an explicit
  `<link rel="icon" type="image/x-icon" href="/favicon.ico">` is
  the smallest defensive fix that covers both well-behaved and
  hard-probing clients.

What
- Regenerated icon assets from the new logo source:
  - `favicon.ico` — multi-resolution ICO with 16/32/48/64 PNG-encoded
    entries. The 16/32 entries are what browser tabs, bookmarks, and
    most crawlers sample; 48/64 cover high-DPI tabs and Windows
    pinned-tile sampling.
  - `favicon.png` — 32×32 PNG (existing slot).
  - `apple-touch-icon.png` — 180×180 PNG (existing slot, iOS
    home-screen).
  - `logo.webp` — 144×144 WebP, 4× the 36px logical size used by
    the header brand mark for crisp retina rendering.
- Added `<link rel="icon" type="image/x-icon" href="/favicon.ico" sizes="any">`
  to both `app/pages/index.astro` and the shared `sub-page-layout`
  so every route under `open-design.ai` advertises the ICO. Existing
  PNG and apple-touch links are preserved — modern browsers will
  still pick the PNG, the ICO catches the hard-probing tail.

Surface area
- Marketing site only. No `apps/web`, `apps/daemon`, contracts, or
  CLI surfaces touched.
- No new dependencies; assets generated locally from the canonical
  source via `magick` + `cwebp` and committed as static files.

Validation
- `pnpm --filter @open-design/landing-page typecheck` — 0 errors.
- File integrity:
  - `favicon.ico` — `MS Windows icon resource - 4 icons,
    16x16, 32x32, 48x48, 64x64`
  - `logo.webp` — `RIFF Web/P image, VP8 encoding, 144x144`
- Manual: `/favicon.ico` will return `image/x-icon` once deployed,
  not the SPA fallback HTML it returns today.

Followup
- Once Cloudflare's edge cache rolls (or is purged), third-party
  favicon caches (Google SERP, Slack link-preview) take days-to-weeks
  to refresh on their own; that lag is expected and not a deploy
  problem.

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-21 17:39:43 +08:00
Marc ChanandGitHub 10192dcc52 fix(ci): catch nix hash drift before merge (#2530)
* fix(ci): catch nix hash drift before merge

* fix(nix): add pnpm hash refresh helper

* chore(nix): drop redundant hash alias

* fix(nix): raise update-hash output buffer

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

* fix(nix): handle current pnpm deps hash

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

* fix(nix): reject non-mismatch hash updates

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 16:08:13 +08:00
lefarcenandGitHub abfe7ba008 fix(web): show feedback prompt on every successful assistant turn (#2529)
* fix(web): show feedback prompt on every successful assistant turn

Previously the thumbs-up/down widget only appeared when the turn produced
an `<artifact>`, wrote a file via Write/Edit, or emitted a live_artifact
event. That left whole categories of completed turns — image/video
generation via `generate_image` / `generate_video`, MCP tool runs, plain
text answers — without any way for the user to rate them.

Drop the `hasArtifactWork` gate from `isFeedbackEligible` and remove the
helper functions that fed it. The remaining filters (streaming in
progress, empty response, unfinished todos, runStatus !== "succeeded")
still suppress the widget for genuinely incomplete turns.

The PostHog `has_produced_files` field is still emitted so the analytics
side can keep slicing feedback by whether the turn produced artifacts.

* test(web): flip artifact-only feedback assertion in AssistantMessage.test.tsx

Companion test file to `chat-feedback.test.tsx` — the same artifact-only
visibility rule was duplicated here and asserted the text-only success
case stays hidden. Flip that case to assert the widget now appears, and
update the file-level comment so the new rule reads cleanly. The
streaming / failed-run / empty-response cases keep their existing
"hidden" assertions; those are still excluded under the new rule.
2026-05-21 15:23:59 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
21e7522574 docs(blog): refresh daily indexing status (#2502)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-21 14:35:50 +08:00
Marc ChanandGitHub 3f7a05e746 fix(visual): freeze GitHub stars in visual captures (#2523) 2026-05-21 13:25:19 +08:00
10940ab7b6 [codex] Update home starter template categories (#2501)
* Update home starter template categories

* fix(web): address PR #2501 review follow-ups

- usePluginFacets.clearFacets() now also resets `mode` to 'all' so the
  empty-state "Clear filters" CTA escapes Saved mode in one click. A
  fresh browser clicking Saved (or Saved combined with a zero-match
  search) was previously stranded on the empty view because the CTA
  only cleared `selection`/`query`.
- Restore the "Link code folder" item in the composer Tools -> Import
  panel. The earlier refactor dropped its `onLinkFolder` wiring and
  left every remaining ImportItem disabled, so chats without linked
  dirs lost the only enabled entry point to `openFolderDialog()` /
  `patchProject({ metadata.linkedDirs })`.

Adds regressions:
- plugins-home-section: Clear filters from the Saved empty state
- ChatComposer.import-menu: folder-link click-through hits the folder
  dialog and patches `linkedDirs`

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: lefarcen <935902669@qq.com>
2026-05-21 13:14:08 +08:00
Marc ChanandGitHub 23d28682da fix(ci): fall back to manifest PR number for visual comments (#2506)
* fix(ci): fall back to manifest PR number for visual comments

* fix(ci): restore authoritative visual PR lookup

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 12:06:41 +08:00
85276df284 chore(deps): patch security override and patch bumps (#2306)
- Add pnpm override: protobufjs 8.4.0 (CVE-2026-45740, GHSA-jggg-4jg4-v7c6)
- Bump postcss 8.5.14 -> 8.5.15 in apps/web (and root override)
- Bump tsx 4.22.2 -> 4.22.3 across all workspace packages

Co-authored-by: Patrick A <259201958+eefynet@users.noreply.github.com>
2026-05-21 11:51:54 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
b7025c4a78 docs(blog): refresh 3-day traffic digest (#2503)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-21 11:50:47 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
5bf128ebdc Update docs/assets/github-metrics.svg (#2493)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-21 11:46:41 +08:00
86dafa9be8 feat(landing): add 19-locale URL routing with full home translations (#2408)
* feat(landing): add 19-locale URL routing with full home translations

Adds locale-prefixed routes (/zh-CN/, /ja/, /de/, …) for 18 non-default
locales while keeping English as the only unprefixed canonical. Generates
proper hreflang + og:locale, points hreflang="en" / x-default at the
unprefixed canonical, and serves localized RSS and plugin search JSON
under each prefix.

Adds a visible language switcher (globe pill + native names) on every
page, replacing the small topbar dropdown. Native-name menu, current
locale marked aria-current, closes on outside click / Escape, only one
open at a time.

Adds app/_lib/home-copy.ts as the source of truth for marketing copy
on the landing page, with full translations for zh-CN, zh-TW, ja, ko,
de, fr, es-ES, pt-BR. Remaining locales (it, pl, hu, ru, uk, tr, ar, fa,
th, id) fall back to English for marketing copy while still getting
fully localized chrome.

Extracts the IntersectionObserver reveal + GitHub stats + wire ticker
script into _components/home-enhancer.astro so localized homepages
animate in the same way as the canonical home.

- New: app/_lib/i18n.ts, app/_lib/home-copy.ts
- New: app/_components/home-enhancer.astro, locale-switcher-enhancer.astro
- New: app/pages/[locale]/{index,[...path]}.astro, blog/rss.xml.ts,
  plugins/search.json.ts

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

* fix(landing): bound localized routing to listing pages only

Detail pages (skills/<slug>, blog/<id>, systems/<slug>, templates/<slug>,
craft/<slug>, plugins/<slug>) no longer fan out across 18 prefixed
locales — they stay at their canonical English URLs. Localized chrome
on listing pages links straight to those English detail URLs.

Generated page count drops from ~6,000+ to ~1,800 and the landing-page
CI build returns to ~50s. Localized homes, listings, and filter index
pages (skills/mode/*, skills/scenario/*, systems/category/*) are all
still produced per locale.

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

---------

Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 11:36:15 +08:00
6359132d04 Polish Design Systems settings gallery controls (#2392)
* Polish design systems gallery settings

* Address design systems settings review

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
2026-05-21 11:30:15 +08:00
Nicholas-XiongandGitHub 7b80e3e85a i18n: add translations for media provider coming soon section (#2415)
* i18n: add translations for media provider coming soon section

- Add 'settings.mediaProviderComingSoonHint' key to all 19 locales
- Replace hardcoded English strings in SettingsDialog.tsx with i18n keys
- Reuse existing 'tasks.comingSoon' and 'settings.agentInstall.docs' keys
- Resolves TODO(i18n) comment at line 5091

* fix: escape single quotes in translation strings

* fix: escape all single quotes in English translation string
2026-05-21 10:56:38 +08:00
Marc ChanandGitHub c45c5c9764 fix(ci): align visual selectors and nix hashes (#2471)
* fix(ci): align visual selectors and nix hashes

* fix(ci): add strict PR visual verification

* fix(ci): repair visual-home captures

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-21 10:45:37 +08:00
Chris TamandGitHub 7b1cc16988 fix(nix): force http:// scheme on bundled caddy site address (#2485)
A bare `host:port` site address lets Caddy pick the listener scheme by
port heuristic, which fights `auto_https off` and surfaces as TLS errors
when the browser hits plain HTTP on a non-standard port. Hardcode the
`http://` prefix in both the Home Manager and NixOS Caddyfile templates
— the bundled proxy is plaintext-only by design, so users who need TLS
run their own front-end with `webFrontend.enable = false`.
2026-05-21 10:44:51 +08:00
ce95266586 [codex] Polish home composer working-directory controls (#2468)
* Polish design system home flows

* Polish home prompt presets

* Polish home working directory controls

* test: align home hero chrome smoke

* fix: stabilize home composer ci checks

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-05-21 00:22:46 +08:00
Marc ChanandGitHub e727168676 chore(ci): expand visual regression coverage (#2381)
* Improve visual diff annotations

* Expand visual regression coverage

* fix(ci): cap visual diff canvas pixels

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

* Stabilize visual regression screenshots

* test(e2e): stub routines for visual snapshot

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

* Expand visual regression surfaces

* fix(e2e): order design system visual mocks

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

* fix(e2e): order design system visual mocks

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

* Tune visual diff box stroke

* fix(e2e): stabilize visual detail mocks

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

* fix(e2e): harden visual diff box helpers

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

* fix(web): preserve deep-linked project bootstrap

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

* fix(e2e): stub automation task mocks

Generated-By: looper 0.8.1 (runner=fixer, agent=opencode)
2026-05-20 22:25:41 +08:00
8193981511 Keep PR 2400 changes without folder pickers (#2462)
* feat(daemon): add project working directory management and editor hand-off functionality

- Introduced new flags for project commands to manage working directories, including `--working-dir` and `--dir`.
- Implemented API routes for listing available editors and opening projects in selected editors.
- Added a hand-off button in the ChatPane header to facilitate opening project folders in local applications.
- Enhanced the HomeHero component to include working directory and design system settings, improving user experience in project creation.
- Created HomeHeroSettingsChips component for inline management of working directory and design system selection.

* feat(chat): implement voice transcription proxy and enhance UI components

- Added a new API route for voice transcription using OpenAI's `/audio/transcriptions` endpoint, allowing users to send audio blobs directly for transcription.
- Integrated multer for handling audio file uploads in memory, ensuring efficient processing without disk storage.
- Updated the HomeHero component to include example prompt suggestions for plugins, enhancing user interaction.
- Introduced the EditorIcon component to visually represent different editors in the hand-off menu, improving the user experience.
- Refined the HandoffButton component to utilize the new EditorIcon, providing a more cohesive interface for selecting editors.
- Enhanced CSS styles for various components to improve layout and responsiveness, including adjustments to tab and button sizes for better usability.

* style(workspace-shell): enhance layout and overflow handling

- Updated CSS for .workspace-shell to ensure full viewport width and height, with proper overflow management.
- Adjusted grid layout to prevent content overflow and maintain responsiveness.
- Modified styles for .workspace-tabs-chrome to improve width handling and prevent overflow issues.

* refactor(chat): remove voice transcription proxy and related components

- Deleted the voice transcription proxy implementation, including the associated API route and multer configuration.
- Removed the MicButton component from the ChatComposer and HomeHero components to streamline the UI.
- Updated HomeHero to include example suggestions without the voice input functionality.
- Adjusted CSS styles for various components to maintain layout consistency after the removal of the MicButton.

* feat(daemon): implement minting of HMAC tokens for working directory management

- Added a new function `mintImportTokenFromCurrentSecret` to generate HMAC tokens bound to a specified base directory, enhancing security for working directory operations.
- Updated the `desktop-auth.ts` file to include the new token minting functionality, which returns structured errors when the desktop auth secret is cleared.
- Introduced new IPC message types for minting import tokens in the sidecar protocol, allowing seamless integration with the daemon's working directory management.
- Enhanced the `WorkingDirPill` component to utilize the new token minting flow for secure directory selection in desktop builds.
- Updated CSS styles for the HomeHero component to accommodate new example suggestion features and maintain layout consistency.

* fix(HomeView): import HOME_HERO_CHIPS constant for improved chip management

- Updated the HomeView component to import the HOME_HERO_CHIPS constant from the chips module, enhancing the management of hero chips within the component.

* feat(daemon): implement mintImportTokenViaSidecar for secure working directory management

- Introduced the `mintImportTokenViaSidecar` function to facilitate the minting of HMAC tokens for desktop-import operations via the daemon's sidecar IPC. This allows CLI commands to bypass authentication when the desktop-auth gate is active.
- Updated the CLI to utilize the new token minting function when setting the working directory, ensuring secure access to trust-gated API endpoints.
- Enhanced the sidecar server to handle minting requests and return structured error messages for improved user feedback.
- Added tests to validate the new token minting functionality and its integration with the working directory management process.
- Refactored related components to support the new token flow, improving overall security and user experience.

* feat(HomeHero): enhance UI components and styles for improved user experience

- Updated HomeHero component to replace active dot indicators with Plug icons for better visual representation of active plugins.
- Adjusted CSS styles for various elements, including padding and dimensions, to enhance layout consistency and responsiveness.
- Introduced new styles for active type icons and improved hover effects for buttons.
- Updated HomeHeroSettingsChips to change button titles and icons for clarity.
- Added tests to ensure proper rendering and functionality of updated components.

* feat(ProjectDesignSystemPicker): enhance design system selection with preview functionality

- Updated the ProjectDesignSystemPicker component to include a preview feature for design systems, allowing users to see a preview of the selected design system.
- Implemented hover functionality to update the preview based on the hovered design system.
- Added fullscreen preview capability for a more immersive experience.
- Enhanced CSS styles for the design system picker to improve layout and responsiveness.
- Introduced tests to validate the new preview functionality and ensure proper interaction within the component.

* feat: refactor project metadata handling and enhance design system picker

- Updated the default scenario plugin ID retrieval to use project metadata, improving the logic for determining the appropriate plugin based on project intent.
- Enhanced the ProjectDesignSystemPicker and related components to support localized design system summaries and categories, improving user experience.
- Introduced new translations for working directory and design system picker components, ensuring better accessibility and usability across different locales.
- Added a new 'live-artifact' project type to the HomeHero chips, expanding the functionality for users creating refreshable artifacts.
- Updated tests to validate the new project metadata handling and design system picker functionalities.

* feat: enhance localization and styling for design system components

- Added French translations for working directory and design system picker components, improving accessibility for French-speaking users.
- Updated CSS styles for the pet task item to ensure consistent padding and layout.
- Introduced a new test suite for HomeHeroSettingsChips to validate localization and design system selection functionality.
- Enhanced ProjectDesignSystemPicker tests to ensure proper localization and interaction with design system categories.

* fix: update .gitignore to include all claude-sessions directories and remove specific session files

- Modified .gitignore to ensure all claude-sessions directories are ignored by using a wildcard pattern.
- Deleted two specific claude-sessions markdown files to clean up unnecessary session data.

* fix: repair home automation ci regressions

* fix: stabilize artifact consistency e2e

* Remove folder picker changes from PR 2400

---------

Co-authored-by: pftom <1043269994@qq.com>
Co-authored-by: qiongyu1999 <2694684348@qq.com>
2026-05-20 22:07:30 +08:00
lefarcenandGitHub 255c3058c5 fix(analytics): app_version=0.0.0 + media providers clicks + lock run_finished error_code (#2453)
* fix(analytics): use state for runtime app version so PostHog gets the real value

`useAppVersion()` stored the fetched `/api/version` result in a `useRef`,
but ref writes do NOT trigger a re-render. The hook therefore kept
returning '0.0.0' forever and the downstream `useEffect` that calls
`client.register({ app_version, ui_version })` never re-ran with the
real version. PostHog dashboards then showed `app_version=0.0.0` and
`ui_version=0.0.0` on every event ever shipped from the web client.

Switching to `useState` lets the resolved version flow through React's
render cycle so the register-on-change effect picks it up. The boot
placeholder still ships as '0.0.0' for the first events before the
fetch resolves (we don't re-emit those), but every event after init
now carries the real daemon-pinned version.

Adds a red-spec at apps/web/tests/analytics-app-version.test.tsx that
went red on the `useRef` shape (`expected '0.0.0' to be '1.2.3'`) and
green on the `useState` shape, so a future refactor can't silently
regress it.

* feat(analytics): wire media providers click events + lock run_finished error_code invariant

Two analytics gaps shipped together because both came out of the same
PostHog spot-check after PR #2390 landed:

1. Settings → Media providers (CSV row "client_type=desktop / mason /
   media_providers") wasn't emitting any ui_click events. The contract
   type `SettingsMediaProvidersClickProps` and helper
   `trackSettingsMediaProvidersClick` were defined but no call site
   used them, so the dashboard showed zero traffic on every element.
   Added the four v2 elements:
   - `reload` on the "Reload from daemon" button
   - `key_input` on every per-provider API key field (onFocus, mirrors
     the BYOK key field pattern in this same dialog)
   - `url_input` on every per-provider base-URL field
   - `clear` on each row's Clear button (fires before the confirm
     dialog so the intent signal is recorded even if the user backs
     out)
   Each event carries `providers_id` (provider.id) and `is_configured`
   (truthy when the row has a stored entry).

2. `run_finished` with `result=failed` was reported as missing
   `error_code` on PostHog. Audited every failure path: the daemon's
   `child.on('close', ...)` handler has several branches that call
   `runs.finish('failed', code, signal)` directly without first
   emitting an SSE `error` event (ACP fatal, agentStreamError fall
   through, child close without diagnostic), leaving
   `run.errorCode === null` in the status body. The existing fallback
   in `server.ts` already derives `AGENT_SIGNAL_*` / `AGENT_EXIT_*` /
   `AGENT_TERMINATED_UNKNOWN` from `signal` / `exitCode` for those
   cases, so the wire emission should never blank out — but the logic
   was inline and had no unit coverage.

   Extracted the result/error_code derivation into
   `apps/daemon/src/run-result.ts` and added 12 unit tests covering:
   - explicit errorCode forwarding
   - signal-only failures
   - exit-code-only failures
   - clean (code=0) failures (ACP fatal shape)
   - cancelled runs (with and without stamped code)
   - empty-string errorCode defensive case
   - status→result mapping for succeeded/canceled/failed/unknown

   All 12 pass — confirming the invariant "result=failed always
   carries error_code" holds for every failure shape the daemon
   produces. The refactor pins that invariant so a future change
   loses test coverage rather than silently regressing on PostHog.

   If `error_code` still looks empty on a live event, share the
   PostHog event JSON + the agent id and I'll dig further — at this
   point the daemon emission itself is exercised end-to-end.
2026-05-20 21:50:11 +08:00
5e9687db4a fix(landing): align logo.webp with brand icon (#2460)
Co-authored-by: koki yanlai xu <koki@kokideMacBook-Air.local>
2026-05-20 21:27:32 +08:00
Tuola-wajandGitHub b1aa62e63c fix(landing-page): restore 'tutorials' in Header active union (#2458) 2026-05-20 21:20:56 +08:00
Tuola-wajandGitHub 69469c639e feat(landing-page): add HTML Anything page and responsive header (#2452) 2026-05-20 20:37:34 +08:00
Siri-RayandGitHub 0ee363f23e Polish design systems library layout (#2421) 2026-05-20 20:31:10 +08:00
e4d6d4e805 fix(landing): keep template preview lookup stable in CI (#2412)
Resolve generated preview thumbnails from both workspace-root and package-root
build layouts so Astro production builds can see the images created by the
landing preview step. A later merge restored the source-relative lookup, which
made /templates render 111 cards with placeholder thumbs despite the PNG files
being deployed.

Co-authored-by: ashley li <ashleyli@ashleydeMacBook-Air-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 18:48:02 +08:00
lefarcenandGitHub 41a33aed9e Reapply "fix(web): demote Plugins and Integrations to nav rail footer (#1806)" (#2360) (#2397)
* Reapply "fix(web): demote Plugins and Integrations to nav rail footer (#1806)" (#2360)

This reverts commit 1ab8758045.

* fixup: align EntryHelpMenu Discord URL with #2386 update

The revert of #2360 brought back EntryHelpMenu.tsx as #1806 originally
added it, with DISCORD_URL = 'https://discord.gg/BYShPgWpq'. #2386 later
rotated the Discord invite to mHAjSMV6gz, but only in the places that
existed on main at the time (EntryShell avatar dropdown + the e2e test);
EntryHelpMenu didn't exist then, so it never got updated. The e2e test
the revert reintroduced asserts the new URL, so the component must
match.
2026-05-20 18:27:48 +08:00
Chris SeifertandGitHub 59c8d72ae4 feat(tweaks): bind toolbar toggle to artifact panel (#2348)
* feat(tweaks): bind toolbar toggle to artifact panel

Wires the host viewer's Tweaks toggle to artifact panels via two
protocols: postMessage __edit_mode_* for agent-generated .twk-panel
artifacts, and the existing class-based bridge for tweaks-skill
.tw-panel artifacts. Toggle disables itself when the artifact exposes
no panel, syncs state when the user closes the panel locally, and no
longer regenerates srcdoc on toggle (no iframe remount).

- bridge: emit od:tweaks-available + MutationObserver-driven
  od:tweaks-panel-state so host learns availability and mirrors local
  closes; transform-based hide preserves the artifact's transition
- host: listen for both od:tweaks-* (bridge) and __edit_mode_*
  (artifact) dialects, send both on toggle, disable button when no
  panel, reset state on file change
- skill: document the two protocols as a host integration contract
- i18n: add fileViewer.tweaksUnavailable for all 13 locales

* fix(tweaks): keep srcDoc path for `.tw-panel` artifacts

The class based tweaks template (`.tw-panel` / `.tw-hidden`) needs the
bridge `injectTweaksBridge` emits, but the default plain HTML preview
URL loads the iframe, which bypasses buildSrcdoc entirely. Without the
bridge there is no `od:tweaks-available` ping, so the toolbar toggle
stays disabled on first load of a tweaks template artifact unless an
unrelated mode (palette, inspect, etc.) coincidentally forces srcDoc.

Add a `tweaksBridge` flag to `shouldUrlLoadHtmlPreview` and detect the
fixed `.tw-panel` / `.tw-hidden` template selectors in the artifact
source via a new `hasTweaksTemplate` helper. FileViewer passes the
detected flag through so tweaks template artifacts pick the srcDoc
render path on first load.

Tests in `file-viewer-render-mode.test.ts` cover the new disqualifier,
the helper positive and negative cases, and combinations with the
existing flags.

* fix(tweaks): resolve v0.7 UI ambiguity between toolbar toggle and palette

After rebasing onto v0.7, three problems surfaced. v0.7 ships a palette
popover button also labeled `Tweaks` with the same sliders icon as the
new toolbar toggle. Toggling that popover flipped render mode (URL load
to srcDoc) and reloaded the iframe, flashing the preview. The resulting
iframe remount caused agent protocol artifacts to re-announce
`__edit_mode_available`, which flipped the toolbar toggle back on
without user input.

Rename the palette popover button to `Themes` (button label, dialog
title, `aria-label`) and swap its icon to a new `paint-bucket` glyph.
The artifact tweaks toggle keeps the `tweaks` sliders icon. Internal
identifiers (`data-testid="palette-tweaks-toggle"`, CSS classes, the
`PaletteTweaks` component name) stay stable so existing tests and
styles still target the same elements.

Drop the auto set true on `__edit_mode_available`; that signal now
flips `tweaksAvailable` only. `syncBridgeModes` posts the current
`tweaksMode` to the artifact (both the bridge dialect and
`__activate_edit_mode` / `__deactivate_edit_mode`) on every iframe
load so the panel matches the toolbar.

Mount both URL load and srcDoc iframes simultaneously, absolutely
positioned and overlapping, with CSS visibility flipping between
them. Toggling render mode no longer reloads the iframe so there is
no flash. `isOurIframe(source)` accepts messages from either iframe
so startup announcements from the hidden iframe are not lost; six
receive filter sites switch from `iframeRef.current?.contentWindow`
to the helper. Sends still target `iframeRef.current`, kept aligned
with the active iframe via a `useEffect`, and a `syncBridgeModesRef`
pushes current bridge state to the now visible iframe whenever the
render mode flips.

Tests that previously asserted exclusive render mode (`url-load`
vs. `srcdoc` presence) now assert the active `data-testid` sits on
the expected iframe via a co-attribute regex. The Draw bar element
picking test switches from a cached frame reference to a `getFrame()`
helper since `data-testid` follows the active iframe across toggles.

Add a `paint-bucket` entry to `Icon` (Lucide style stroke icon).

* fix(tweaks): scope `od:tweaks-available` to the active iframe

The dual iframe setup mounts both the URL load and srcDoc iframes at
once and accepts postMessage events from either via `isOurIframe`. The
srcDoc iframe always carries the always injected tweaks bridge, which
runs `document.querySelector('.tw-panel')` on mount and posts
`{ type: 'od:tweaks-available', available: false }` for any artifact
that does not ship the class based panel. For an agent protocol
artifact (`.twk-panel`, `__edit_mode_*`), the URL load iframe correctly
announces `__edit_mode_available` and the host sets
`tweaksAvailable = true`. The hidden srcDoc iframe's `available: false`
ping arrives shortly after and overrides that to false, silently
disabling the toolbar button.

Scope `od:tweaks-available` to the active iframe only by re-checking
`ev.source === iframeRef.current?.contentWindow` before applying it.
`__edit_mode_available` and `__edit_mode_dismissed` stay accepted from
either iframe so the artifact's own announcement still drives the
toolbar toggle across render mode flips.

Spotted by Siri-Ray on PR #1643.

* fix(tweaks): start the toolbar toggle ON when the artifact mounts its panel visible

Both tweaks dialects (the class-based `.tw-panel` skill template and the
`.twk-panel` agent-generated edit-mode protocol) mount their panel visible
by default. Before this change the toolbar `Tweaks` toggle started in the
OFF state regardless, so the user saw the panel but had to click
toggle-on → toggle-off to actually hide it — confusing because the toggle
disagreed with what they could plainly see in the preview.

Two changes wire the initial state through to the toolbar:

- `srcdoc.ts` (class-based dialect): the tweaks bridge's `onReady` now
  fires `postState()` alongside `postAvailability()`. `postState()` reads
  `!panel.classList.contains('tw-hidden')` and posts the artifact's actual
  initial visibility, so the host's existing `od:tweaks-panel-state`
  handler picks it up and mirrors it into `tweaksMode`. Previously only
  MutationObserver-driven changes were posted, so the host never learned
  the artifact's initial state.

- `FileViewer.tsx` (twk-panel dialect): the agent dialect's
  `__edit_mode_available` carries no visibility payload, so we infer
  default-open from the fact that the artifact bothered to announce
  availability at all (the SDK pattern is `useState(true)`). Mirror that
  into `tweaksMode` exactly once per file (tracked by
  `firstEditModeAvailableSeenForFileRef`), so an iframe remount triggered
  by, e.g., flipping render mode through the Themes popover does not snap
  a user-driven OFF back to ON.

Also fix a runtime `ReferenceError: panel is not defined` regression
this same change introduced when first written with backticks inside the
new code comment — the comment lived inside a `\`...\``-delimited script
template literal, so the embedded backticks closed and reopened the outer
literal and broke the bridge's JS body. Replaced with plain text.

Validation: web typecheck clean, 1597/1597 tests pass. Manually verified
with a `.twk-panel` artifact: open file → tweaks toggle is ON, panel
visible → one click hides both.

* fix(tweaks): seed bridge state from the panel's authored class, not from the host hidden attribute

The bridge installs `data-od-tweaks-hidden` on `<html>` synchronously in
`<head>` so the panel never flashes on initial paint. That attribute is
therefore *always* present by the time `onReady()` fires, which meant the
previous `applyClassesToPanel(!hasAttribute(...))` call unconditionally
forced `.tw-hidden` onto the panel, the follow-up `postState()` read that
forced-hidden class, and the host saw `visible: false` even when the
artifact had authored the panel as default-visible. The PR-1643 attempt
at "start ON when the artifact mounts visible" therefore still reported
OFF for the class-based template path.

Read the panel's authored class state first (the artifact body has just
parsed, so the panel's class is what the artifact wrote and nothing
else has touched it yet), then drive the attribute, the applied class,
and the `od:tweaks-panel-state` post from that captured value:

```ts
var panel = panelEl();
var initialVisible = !!panel && !panel.classList.contains('tw-hidden');
document.documentElement.toggleAttribute('data-od-tweaks-hidden', !initialVisible);
applyClassesToPanel(initialVisible);
attachObserver();
postAvailability();
postState();
```

A default-visible `.tw-panel` now reports `visible: true` on mount, the
host mirrors that into `tweaksMode = true`, and the toolbar Tweaks toggle
starts in the ON state instead of disagreeing with what the user sees in
the preview. The `.twk-panel` agent-protocol path is unaffected; its
initial-state mirror still goes through the
`firstEditModeAvailableSeenForFileRef` guard in `FileViewer.tsx`.

Surfaced by Siri-Ray in https://github.com/nexu-io/open-design/pull/1643#discussion_r3263571196.

Validation: web typecheck clean, 1597/1597 tests pass.

* fix(tweaks): re-mirror __edit_mode_available default-open state when switching .twk-panel files

The once-per-file guard that mirrors a `.twk-panel` artifact's
default-open state into the toolbar `tweaksMode` lives inside a
`window.addEventListener('message', ...)` handler installed in a
`useEffect(..., [])` with an empty dep list. The handler therefore
closed over the first-render `file.name`. After opening one
`.twk-panel` artifact, `firstEditModeAvailableSeenForFileRef.current`
got set to that first file; switching to a second `.twk-panel` file
left the message listener still comparing the new artifact's
`__edit_mode_available` against the stale captured name, so the
guard never re-fired and the toolbar stayed OFF while the new
artifact's panel was clearly visible — exactly the mismatch the
guard was supposed to prevent on initial load.

Add `file.name` to the listener effect's dep list so the handler
gets a fresh closure on every file switch. The bridge-message setters
(`setTweaksAvailable`, `setTweaksMode`), `isOurPreviewIframeSource`,
and `firstEditModeAvailableSeenForFileRef` are stable across renders,
so re-binding the listener has no other side effects beyond updating
the captured `file.name`.

Surfaced by Siri-Ray in
https://github.com/nexu-io/open-design/pull/1643#discussion_r3266838151.

Red-spec regression test added: `FileViewer tweaks toolbar > mirrors
__edit_mode_available default-open state for each switched-to
.twk-panel file`. Verified to go red on the bug (deps `[]`) and green
on the fix (deps `[file.name]`).

Validation: web typecheck clean, 1598/1598 tests pass (was 1597).

* i18n(tweaks): add fileViewer.tweaksUnavailable to the remaining 6 locales

The toolbar's disabled-Tweaks tooltip key landed in 13 locale files but
6 were missed (ar, fr, id, it, th, uk). Those locales were still falling
through to the English string via the `...en` spread, which contradicts
the repo convention that every key be defined explicitly in each locale.
Add the translation alongside the existing `fileViewer.tweaks` entry so
the full set of 19 locales now ships native copy for the disabled state.

Surfaced by Siri-Ray in
https://github.com/nexu-io/open-design/pull/1643#discussion_r3267654385.

* fix(tweaks): respect default-closed dynamic panels in __edit_mode_available

Protocol A in `design-templates/tweaks/SKILL.md` documents that the
artifact may default the panel to either open or closed and the host
should sync its toolbar toggle to whichever state the artifact reports.
The previous handler ignored that and unconditionally mirrored
availability into `tweaksMode = true`, so a default-closed dynamic
artifact would be force-opened the moment `syncBridgeModes` ran and
fired `__activate_edit_mode` — the artifact could not stay closed even
though the contract said it could.

Extend the message shape so the artifact can report its initial state
on the same payload:

  { type: '__edit_mode_available', visible?: boolean }

The host now reads `data.visible`:

- omitted          → treat as `true` (back-compat: existing artifacts
                     emitting the legacy zero-arg shape mount with the
                     panel already on screen, which is the SDK pattern
                     `useState(true)`).
- `visible: true`  → toolbar starts ON.
- `visible: false` → toolbar starts OFF, panel stays closed; the user
                     opts in by clicking the toggle, which then fires
                     `__activate_edit_mode` via the existing
                     `syncBridgeModes` path.

Update `design-templates/tweaks/SKILL.md` to document the new optional
field alongside the legacy shape.

Surfaced by Siri-Ray in
https://github.com/nexu-io/open-design/pull/1643#discussion_r3269955351.

Red-spec regression test added: `FileViewer tweaks toolbar > respects
__edit_mode_available { visible: false } for default-closed dynamic
artifacts`. Verified red without the fix (always-true mirror) and green
with the fix (`data.visible !== false`).

Validation: web typecheck clean, 1599/1599 tests pass.
2026-05-20 18:00:49 +08:00
open-design-bot[bot]GitHubopen-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
7905e72962 docs(blog): refresh 3-day traffic digest (#2349)
Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
2026-05-20 18:00:22 +08:00