open-design/apps/landing-page/app/_components
Jane 3f4fd58937
Some checks failed
ci / Detect CI change scopes (push) Successful in 0s
visual-baseline / Capture visual baselines (push) Waiting to run
landing-page-ci / Validate landing page (push) Failing after 2s
landing-page-staging / Deploy landing page to staging (push) Has been skipped
nix-check / build (push) Failing after 2s
ci / Validate Nix flake (push) Has been skipped
ci / Preflight (push) Failing after 2s
ci / Workspace unit tests (push) Failing after 2s
ci / Daemon workspace tests (push) Failing after 1s
ci / Web workspace tests (push) Failing after 1s
ci / Browser tests (push) Failing after 1s
ci / Build workspaces (push) Failing after 2s
ci / Validate workspace (push) Failing after 0s
ci / Runtime trace (push) Has been skipped
feat(landing-page): surface Discord + X in header, restructure site footer (#3230)
* feat(landing-page): surface Discord + X in header, restructure site footer

Two related public-chrome adjustments:

- **Header gains compact Discord + X icon buttons.** Both community
  channels were previously buried in the footer, so the typical
  visitor never saw them on a page-deep scroll. They now sit before
  the Download / Star CTAs in `nav-side`, share the ghost-button
  outline language, and stay icon-only with `aria-label` so they
  read as social affordances rather than competing with the text
  CTAs. At ≤1080px the icon buttons hide alongside the existing
  ghost CTA, so the bar still collapses cleanly into the hamburger
  panel — Star stays in the bar at every breakpoint.

- **Footer restructured into 4 columns: Products / Plugins /
  Resources / Connect.** The old `Plugins / Open Design / Connect`
  three-column layout muddled three different things — sister
  products, the artifact catalogue, and contributor channels —
  under one roof, so visitors hunting for "the other thing this
  team makes" had nowhere obvious to go.
  - **Products** (new) lists the team's apps: Open Design (links
    to homepage) and HTML Anything. Two entries by design — adding
    more products without an editorial pass would dilute the
    column.
  - **Plugins** mirrors the topbar `Plugins` dropdown verbatim:
    Templates / Skills / Systems / Craft, with no count prefix on
    Systems / Craft so it reads identically to the nav.
  - **Resources** (renamed from `Open Design`) carries the
    docs-style links: Official source / Quickstart / Agents locaux
    / Compare / Claude Design alternative. The old column heading
    was confusing because the OD logo + brand name already sit
    under the column.
  - **Connect** gains an X / Twitter row pointing at
    `@nexudotio`. The brand entries on this column are
    contributor / community surfaces only — code, releases,
    chat, social, RSS, contact form.

Implementation:

- `_components/header.tsx` — `DISCORD` and `X_TWITTER` consts at
  the top alongside `REPO`. Two `<a class="nav-icon">` blocks with
  inline SVG before the existing Download / Star CTAs.
- `_components/site-footer.astro` — `HTML_ANYTHING` and `NEXU_IO`
  consts. `<div class="sub-footer-col">` re-ordered to put
  Products first, Plugins second (no longer carries `counts.*`
  values), Resources third, Connect fourth (with the new X / Twitter
  row).
- `globals.css` — `.nav-icon` rule cloned from the ghost CTA's
  visual language (transparent + 1px line, fills on hover) but
  square (36×36 round) so it reads as a social-icon affordance.
  Added `display: none` for `.nav-side .nav-icon` to the existing
  ≤1080px and ≤880px media queries so the icons follow the same
  collapse behaviour as the Download CTA.
- `sub-pages.css` — `.sub-footer-grid` switches from
  `1.6fr 1fr 1fr 1fr` to `1.4fr 1fr 1fr 1fr 1fr` (brand + 4
  columns). At ≤1080px it falls back to a 3-column shape so each
  column has room to breathe; at ≤720px it stays a single column
  (existing behaviour).
- `i18n.ts` — adds `products`, `resources`, `xTwitter`,
  `sisterProjects`, `htmlAnything`, `nexuIo` to `LandingUiCopy.footer`
  (the last three are kept around even though `sisterProjects` is no
  longer rendered after the column was renamed Products — they're
  harmless and avoid churning the type if a future iteration brings
  the Sister-projects framing back). All 17 non-English landing
  locales gain translations for the new keys via the existing
  `LOCALIZED_LANDING_FOOTER_COPY` map (and the `LANDING_UI_COPY_OVERRIDES`
  block for `zh` / `zh-tw`). Translations were generated with
  `claude-haiku-4-5` over OpenRouter, with explicit instructions
  to keep "Open Design", "HTML Anything", and "X / Twitter" in
  English and to render "Products" / "Resources" in sentence case
  per locale convention. Spot-checked against rendered pages on
  `/zh/`, `/zh-tw/`, `/ja/`, `/ko/`, `/de/`, `/fr/` (and `/ar/` for
  RTL) for natural phrasing.

Validation: `pnpm --filter @open-design/landing-page typecheck` ->
0 errors / 0 warnings; local dev server smoke-tested on en root
(`/html-anything/`) and 5 locale variants (`/zh/`, `/zh-tw/`,
`/ja/`, `/de/`, `/fr/`) — header renders 2 nav-icon buttons,
footer renders 4 localized column headings in the correct order
with the right link targets.

* fix(landing-page): address PR #3230 review — locale-aware HTML Anything link + drop unused const

Two non-blocking inline review points from @PerishCode on PR #3230:

- The HTML Anything entry in the new Products column hardcoded
  `https://open-design.ai/html-anything/` via a top-level
  `HTML_ANYTHING` const, but `/html-anything/` is a real localized
  route in this app (`pages/[locale]/html-anything/index.astro`)
  and `open-design.ai` is the same site's live domain. A visitor
  on `/zh/…` clicking through landed on the English route and lost
  locale context, and hardcoding the production domain meant a
  preview build would surface a link that bounces visitors back
  to prod. Switch to `href('/html-anything/')` so the locale prefix
  + the current site's domain (resolved by `localizedHref`) are
  honored, matching every other footer link.

- `NEXU_IO` was declared at the top of the component but never
  referenced — leftover from an earlier iteration that listed
  `nexu.io` as a Sister-projects entry before the column was
  renamed Products and reduced to OD + HTML Anything. Removed.

No behavior change beyond the locale routing fix; the i18n keys
and column structure stay as they landed in the original commit.

* fix(landing-page): correct nav-icon comment to match actual responsive behaviour

The JSX comment introduced for the new Discord + X icon buttons in
PR #3230 claimed the icons "survive at narrow widths while text-only
nav items get pushed off". The CSS that shipped in the same PR does
the opposite: both `@media (max-width: 1080px)` and `@media (max-width:
880px)` blocks add `.nav-side .nav-icon { display: none; }`, so at
narrow widths the icons collapse alongside the ghost Download CTA
while the text nav <ul> moves into the hamburger panel — only the
Star CTA remains visible in the bar.

Rewrite the comment to describe the actual responsive contract so
the next reader of `header.tsx` doesn't have to cross-reference
`globals.css` to figure out which surface stays. Reviewer flag from
@PerishCode on PR #3230.

No code-path change; comment-only.

* fix(landing-page): correct sub-footer 1080px comment to describe actual 3-column grid

The CSS comment introduced for the new sub-footer grid claimed the
≤1080px breakpoint drops to "brand + 2x2 grid of columns" — but the
rule produces a 3-column grid, not a 2x2.

`.sub-footer-grid` has 5 children at this breakpoint (the brand
block + the four footer columns) and `.sub-footer-brand` carries
no `grid-column` span, so with `grid-template-columns: 1.6fr
repeat(2, 1fr)` they flow as: row 1 = brand · Products · Plugins,
row 2 = Resources · Connect · empty cell. The brand sits inline
with two columns rather than on its own, and the four content
columns are not a clean 2x2.

The layout itself is fine; only the comment misleads the next
reader about how the columns wrap. Same flavor as the `header.tsx`
icon comment fixed in 744daec — describe what the rule actually
does so the comment doesn't drift from the CSS. Reviewer flag
from @PerishCode on PR #3230.

Comment-only change.

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-29 05:59:24 +00:00
..
favicon-links.astro feat(landing-page): SEO surfaces, schema upgrades, manifest — cherry-pick from #2469 (#2596) 2026-05-21 23:03:21 +08:00
google-analytics.astro fix(landing): wire GA4 rollout config (#2615) 2026-05-22 14:56:58 +08:00
header-enhancer.astro feat(landing-page): detail pages — interactive preview, share row, dual CTAs (#2679) 2026-05-22 20:47:59 +08:00
header.tsx feat(landing-page): surface Discord + X in header, restructure site footer (#3230) 2026-05-29 05:59:24 +00:00
home-enhancer.astro perf(landing): preconnect api.github.com + rAF-throttle scroll listener (#2666) 2026-05-22 14:06:39 +08:00
lazy-img.astro perf(landing): edge-cache HTML and precise-load thumbnails (#2235) 2026-05-19 19:14:25 +08:00
locale-switcher-enhancer.astro feat(landing): add 19-locale URL routing with full home translations (#2408) 2026-05-21 11:36:15 +08:00
locale-switcher-script.astro feat(landing-page): replicate #2469 SEO content with deploy + regression fixes (#2605) 2026-05-22 00:59:11 +08:00
plugin-row.astro feat(landing-page): localize plugins library across 18 locales (#3010) 2026-05-27 09:30:59 +00:00
precise-lazyload.astro feat(landing-page): rebuild plugins library to mirror in-app taxonomy (#2926) 2026-05-26 02:49:58 +00:00
resource-hints.astro perf(landing): preconnect api.github.com + rAF-throttle scroll listener (#2666) 2026-05-22 14:06:39 +08:00
seo-head.astro ci(landing): split landing deploy into staging gate + manual production (#2994) 2026-05-26 14:05:04 +00:00
site-footer.astro feat(landing-page): surface Discord + X in header, restructure site footer (#3230) 2026-05-29 05:59:24 +00:00
skill-row.astro feat(landing-page): rebuild plugins library to mirror in-app taxonomy (#2926) 2026-05-26 02:49:58 +00:00
sub-page-layout.astro fix(landing): wire GA4 rollout config (#2615) 2026-05-22 14:56:58 +08:00
system-card.astro feat(landing-page): replicate #2469 SEO content with deploy + regression fixes (#2605) 2026-05-22 00:59:11 +08:00
template-card.astro feat(landing-page): card grid + share popover for /plugins/templates/ (#3185) 2026-05-28 11:17:56 +00:00
topbar.astro feat(landing-page): replicate #2469 SEO content with deploy + regression fixes (#2605) 2026-05-22 00:59:11 +08:00
wire.tsx fix: sync landing source-of-truth paths (#2066) 2026-05-20 11:44:04 +08:00