open-design/.github/workflows
Jane 40ae0836dd
feat(landing-page): rebuild plugins library to mirror in-app taxonomy (#2926)
* feat(landing-page): synthesize fallback preview cards for instruction skills

The skill catalog renders a diagonal-stripe placeholder for any skill
without a runnable example.html, which leaves ~70% of /skills/ as a
field of bare grey thumbs (instruction skills like copywriting,
creative-director, color-expert, brainstorming have no static demo
because their output depends on the agent's input).

Synthesize a typographic editorial card from each SKILL.md frontmatter
and screenshot it through the same Playwright pipeline that handles
real demos, so every catalog row carries a thumbnail. Cards include:

  - OPEN DESIGN · SKILL top label + Nº NNN index (1..96 over the
    instruction subset, sorted by od.featured then alphabetical)
  - Big Playfair Display slug with a coral dot accent
  - Italic serif description clamped to 3 lines
  - mode/category chips + "Curated from <author>" attribution
  - Warm-paper background with a subtle 135° stripe to thread the
    landing's existing visual language

Bundle a few related improvements caught while building this:

  - SkillRecord gains a `kind: 'instruction' | 'template'` field so
    the detail page can render differently per kind (instruction
    skills now render the SKILL.md body inline as "About this skill",
    template skills keep the click-to-expand iframe demo).
  - Catalog row thumbnails switch from the bespoke IntersectionObserver
    pipeline to native `loading="lazy"` (with eager + fetchpriority=high
    on the first 3). The observer's swap latency stranded mid-list
    rows on the SVG placeholder during fast scrolls; native lazy uses
    the browser's 1250-3000px lookahead so the placeholder flash is
    gone.
  - precise-lazyload rootMargin bumped to 1500px for any remaining
    data-precise-src callers.
  - CI cache key for generated previews now folds in
    fallback-preview-card.ts so a template tweak invalidates the cache.

* feat(landing-page): rebuild plugins library to mirror in-app taxonomy

The marketing site's `/skills/`, `/templates/`, `/systems/`, `/craft/`
top-level entries were organized around author-supplied `od.mode` /
`od.scenario` taxonomies that visitors never see inside Open Design
itself. The in-app Plugins home (`apps/web/src/components/plugins-home/`)
groups every bundled plugin by the artifact it produces — Prototype,
Live Artifact, Slides, Image, Video, HyperFrames, Audio — and that's
the language users encounter the moment they open the product.

This PR rebuilds the public library around the same taxonomy and the
same data source so a visitor reading "Templates · 231" on the
marketing site sees the same 231 inside the app.

## What changes

- New top-level `/plugins/` hub: four tiles (Templates, Skills,
  Systems, Craft) with live counts pulled straight from
  `plugins/_official/<bucket>/<slug>/open-design.json` — the daemon's
  bundled-plugin registry.
- `/plugins/templates/` lists every bundled plugin that lands in one
  of the seven artifact kinds. Seven sub-routes
  (`/plugins/templates/prototype/`, `/deck/`, `/image/`, `/video/`,
  `/hyperframes/`, `/audio/`, `/live-artifact/`) carry the same chip
  rail with an active state, so visitors can switch artifact kinds
  with one click without losing the rail.
- Each artifact-kind sub-route shows a Scene chip rail when the kind
  has scene buckets (Prototype / Slides / Image / Video each get
  five-six). The Scene filter runs client-side via inline `style.display`
  toggles; URLs stay one-per-kind so we don't multiply 25 × 18 locales
  worth of static pages just for filter combinations.
- `/plugins/skills/` collects the instruction-only entries (mode
  doesn't fit any of the seven kinds) — copywriting, color theory,
  creative direction, brainstorming, etc.
- `/plugins/systems/` lists the 150 bundled design systems via the
  legacy SystemCard renderer (palette swatches, tagline) so the
  visual treatment matches the in-product library.
- `/plugins/craft/` keeps the existing craft principles list.
- `/plugins/<manifest-id>/` detail pages built from manifest metadata:
  hero (poster image or playable Cloudflare Stream MP4 for video
  templates), author / mode / scenario / tags, GitHub source link.
  Author URLs pointing at the `nexu-io` org redirect to the
  `nexu-io/open-design` repo so the attribution is actionable.
- Header dropdown labelled "Plugins" with the four sub-routes; footer
  Library column updated to match.
- Old marketplace registry pages under `/plugins/` and
  `/[locale]/plugins/` removed (they were a dormant placeholder UI;
  the actual manifests it tried to load lived nowhere). The rest of
  the legacy plugin-registry loader stays intact for any other
  consumer.

## Preview generation

Bundled plugins ship `od.preview.poster` URLs on R2 for image and
video templates; those are used directly. The other 293 entries
(html-mode examples, design-systems, scenarios) had no poster, so
`generate-previews.ts` was extended to:

1. Screenshot a local `example.html` referenced by `od.preview.entry`
   when present (134 examples).
2. Synthesize the same typographic editorial card the SKILL.md
   fallback uses, sourced from manifest title / description / mode /
   author (159 systems / scenarios / misc).

Output lands at `public/previews/plugins/<manifest-id>.png`. The
catalog loader checks for the local file when the manifest carries no
poster URL, so the row's `<img src>` always has something to point at.

Result: every catalog row and every detail page has a thumbnail;
visiting `/plugins/templates/video/` shows the same 48 entries the
in-app Plugins home shows, hyperframes the same 13, etc.

## Counts

- Templates: 231 (Prototype 59 + Slides 59 + Image 46 + Video 48 +
  HyperFrames 13 + Audio 1 + Live Artifact 5)
- Skills: 15
- Systems: 150
- Craft: 11

Atoms (13 infrastructure plugins, `od.kind === 'atom'`) are filtered
to mirror the in-app behaviour.

* fix(landing-page): use Astro 6 render() helper for SKILL.md body

Astro 6 dropped `entry.render()` in favour of a top-level `render(entry)`
helper imported from `astro:content`. The instruction-kind skill detail
page was still using the legacy method, which compiled locally on Astro
6 only because tsx ignored the missing prototype method, but `astro
check` (run in CI) flagged it as ts(2551) and broke the workflow.

---------

Co-authored-by: Joey-nexu <joeylee12629@gmail.com>
2026-05-26 02:49:58 +00:00
..
actionlint.yml fix(ci): lint workflow changes with actionlint (#2742) 2026-05-23 12:12:55 +08:00
agent-pr-explore.lock.yml ci: add agent explore workflow placeholder (#2830) 2026-05-24 20:22:51 +08:00
blog-3day-report.yml fix(ci): lint workflow changes with actionlint (#2742) 2026-05-23 12:12:55 +08:00
blog-indexing-monitor.yml fix(ci): lint workflow changes with actionlint (#2742) 2026-05-23 12:12:55 +08:00
blog-indexing-on-deploy.yml Fix blog indexing status PR base (#2106) 2026-05-19 18:08:01 +08:00
ci.yml fix(ci): lint workflow changes with actionlint (#2742) 2026-05-23 12:12:55 +08:00
contributor-card-bot.yml fix(contributor-bot): serialize runs to avoid state.json races and duplicate cards (#1707) 2026-05-14 20:01:13 +08:00
critique-conformance.yml feat(daemon): Critique Theater Phase 16 (M-phase rollout ratchet + /api/critique/conformance) (#1499) 2026-05-14 11:05:57 +08:00
discord-resolved.yml ci: skip upstream-only workflows on forks (#1586) 2026-05-14 14:27:23 +08:00
docker-image.yml fix(ci): only run docker image workflow for release tags (#1916) 2026-05-16 22:32:33 +08:00
fork-pr-workflow-approval.yml ci: gate fork PR workflow auto-approval (#2683) 2026-05-23 11:48:36 +08:00
landing-page-ci.yml feat(landing-page): rebuild plugins library to mirror in-app taxonomy (#2926) 2026-05-26 02:49:58 +00:00
landing-page-deploy.yml fix(landing-page): speed up landing-page CI builds (#2734) 2026-05-23 00:30:31 +08:00
metrics.yml fix(ci): use open-design-bot for metrics PRs (#1910) 2026-05-16 21:52:37 +08:00
nix-check.yml chore: optimize CI and beta release runtime (#2231) 2026-05-19 18:06:28 +08:00
pr-author-inactivity.yml fix(ci): anchor PR inactivity clock to author responses (#2185) 2026-05-19 13:59:15 +08:00
refresh-contributors-wall.yml ci: skip upstream-only workflows on forks (#1586) 2026-05-14 14:27:23 +08:00
release-beta.yml fix: defer Windows packaged updater installer (#2575) 2026-05-21 19:13:18 +08:00
release-preview.yml Fix packaged auto-update release validation (#2565) 2026-05-21 18:15:53 +08:00
release-stable.yml Fix packaged auto-update release validation (#2565) 2026-05-21 18:15:53 +08:00
seo-daily-report.yml fix(ci): lint workflow changes with actionlint (#2742) 2026-05-23 12:12:55 +08:00
stale-issues.yml ci: add PR-author and stale-issue inactivity workflows (#2055) 2026-05-18 16:45:37 +08:00
visual-baseline.yml chore(ci): add visual regression PR workflow (#2372) 2026-05-20 15:05:59 +08:00
visual-pr-capture.yml ci: gate fork PR workflow auto-approval (#2683) 2026-05-23 11:48:36 +08:00
visual-pr-comment.yml fix(ci): lint workflow changes with actionlint (#2742) 2026-05-23 12:12:55 +08:00
visual-pr-verify.yml fix(ci): align visual selectors and nix hashes (#2471) 2026-05-21 10:45:37 +08:00