From 7e390a1aaa6c5740ae1827797e305675ffd7f740 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Tue, 6 Oct 2026 12:14:24 +1100 Subject: [PATCH 1/4] feat(header): add a Developers menu and a Skillgen setup page The header listed CLI and Make a skill as loose links, and the MCP server, the SDK and the skilld-skillgen GitHub App had no entry point at all. One Developers menu now holds them as cards, as nuxtseo.com groups its tools. The skilld-skillgen App had no page that explains its requirements or how to install it, so /skillgen adds one. It states the pilot limit while the Worker processes only GITHUB_PILOT_REPOSITORIES. --- COPY.md | 10 +- DESIGN.md | 3 +- GLOSSARY.md | 9 + app/app.vue | 88 +++----- app/components/_HeaderNavigation.vue | 190 ++++++++++++++++++ app/utils/developer-menu.ts | 65 ++++++ layers/marketing/app/pages/skillgen.vue | 131 ++++++++++++ layers/marketing/app/utils/page-admissions.ts | 1 + package.json | 1 + pnpm-lock.yaml | 69 ++----- pnpm-workspace.yaml | 3 + test/a11y.spec.ts | 36 ++++ 12 files changed, 491 insertions(+), 115 deletions(-) create mode 100644 app/components/_HeaderNavigation.vue create mode 100644 app/utils/developer-menu.ts create mode 100644 layers/marketing/app/pages/skillgen.vue diff --git a/COPY.md b/COPY.md index 474a9e8f..1082b165 100644 --- a/COPY.md +++ b/COPY.md @@ -37,7 +37,15 @@ These exact strings. Do not paraphrase them per page. | Home section: trending | Trending skills this week. | guidance only: the homepage trending section heading | | Home section: changes | Keep up with skill changes. | guidance only: the homepage section heading for watching and the digest | | Home section: authoring | Write a skill for your project. | guidance only: the homepage section heading for making a Skill | -| Nav: CLI | CLI | guidance only: the header nav and the mobile menu item that link `/cli` | +| Nav: developers | Developers | guidance only: the header menu trigger, and the group label in the mobile menu. The menu holds the four cards below | +| Nav: CLI | CLI · Search, run, install, and keep Skills current. · Install the CLI | guidance only: the first card in the Developers menu: name, line, action. Links `/cli`. The mobile menu shows the name only. The line is the CLI line and the action is the CLI install label, so change those first | +| Nav: MCP server | MCP server · For ChatGPT, Claude, and any app that speaks MCP. · Add the MCP server | guidance only: a Developers menu card. Links `/developers?setup=mcp`. The line is the MCP setup card on `/developers`, and the action is its section heading | +| Nav: SDK | SDK · For your own code, with the TypeScript SDK or plain HTTP. · Call the skilld API | guidance only: a Developers menu card. Links `/developers?setup=api`. The line is the API setup card on `/developers`, and the action is its section heading | +| Nav: make | Make a skill · Guides and three authoring Skills to write and review your own. · Get the steps | guidance only: a Developers menu card. Links `/make-skill`. The line is the Step 05 description | +| Nav: Skillgen | Skillgen · Keeps your package skill current with a draft pull request after each release. · Set up Skillgen | guidance only: the last Developers menu card. Links `/skillgen` | +| Nav: setup guides | All setup guides | guidance only: the link under the Developers menu cards. Links `/developers` | +| Skillgen lead | Keep your package skill current. After each release tag, Skillgen opens a draft pull request that updates the Skill in your repository. You review it and decide what merges. | guidance only: the `/skillgen` line under the H1. Its first two sentences are the page's meta description | +| Skillgen pilot | Skillgen is in a pilot. It runs only on repositories in the pilot. | guidance only: the `/skillgen` note while the Worker reads `GITHUB_PILOT_REPOSITORIES`. Remove it when the pilot opens | | CLI H1 | The skilld CLI | guidance only: the `/cli` H1 and its OG title | | CLI line | Search, run, install, and keep Skills current. | guidance only: the `/cli` line under the H1. It is the CLI's own `--help` line, so change it in the CLI first | | CLI intro | Give your Agent Skills that real maintainers write. A run reads the current source every time, and one command updates the Skills you install. Install the skilld Skill once, and your Agent searches and loads Skills on its own. | guidance only: the `/cli` intro under the line | diff --git a/DESIGN.md b/DESIGN.md index 1b3b194d..21d3d7d1 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -78,7 +78,7 @@ Practically: - One accent color used sparingly (10% of surface area, max) - UI chrome in monospace at small sizes; content in the sans-serif - Borders, not shadows, define boundaries -- No glow, no gradient, no blur, no decorative flourish in UI chrome. The textures in "Brand System" are the only decoration, and each has one job +- No glow, no gradient, no blur, no decorative flourish in UI chrome. The textures in "Brand System" are the only decoration, and each has one job. The cards in the header's Developers menu are the one exception: each carries one atmosphere layer - Compact components: tight padding, defined shapes, minimal radius - Whitespace is intentional structure, not generous filler @@ -460,3 +460,4 @@ These are editorial sets, not necessarily database collections yet. If a set has - **Trending shares the /skills shell**: `/skills/trending` uses the full-width layout from `/skills`. Its heading replaces `CompactPageHeader` and lines up with the results column. A sticky 14rem sidebar holds the range links, then the weekly CTA and the skilld install. Nothing sits right of the board, so the board takes every column the sidebar leaves. Rows switch on their own width, and the post carousel shows two cards where it has room. On narrow screens the ranges are a compact row above the board, and the CTA stays after the fifth row. Harlan asked for this on 2026-10-06. It supersedes the 2026-10-01 call that dropped the 9/3 sidebar for taking a quarter of the board's width: that sidebar sat right of a 64rem board, and this one sits left of a board that runs the full page width. - **Trending rows scan in one pass**: the rank is a plain mono number, and the first three are a step darker. Each metadata line runs source, stars, then the signal that ranked the row, and an empty slot renders nothing. Descriptions stop at two lines, the run chip is as wide as its command, and the post carousel shows whole cards only. The sidebar invitation drops the email preview and the card. Its button is the rail's one solid rose element, so the install chip beside it inks its dot. Harlan asked for this polish on 2026-10-06. - **A six-step lifecycle band replaces the four tiles**: under the hero, one band maps the whole product in its real order: find, run, install or fork, keep current, make, build on. The site and the CLI share one line. Each step is one link: a mono `01` marker and step name, then one sans line that opens with its pitch line where COPY.md has one. A line of stone dots joins the steps. Run, the default, carries the band's one rose dot, so no step lights rose on hover. Six columns from 1024px; below that a vertical list with the dots down the left. Keep the band no taller than the tiles it replaced: the hero and the band must fit a 1440×900 viewport. Harlan approved it on 2026-10-06. +- **A Developers menu groups the build surfaces**: the desktop header keeps Trending Skills and Find Skills as links, and folds CLI, MCP server, SDK, Make a skill and Skillgen into one Developers menu, as nuxtseo.com does. The trigger is a button, so a keyboard opens the panel without leaving the page; the panel's last link reaches `/developers`. Each item is a card with a lucide icon tile and one `.editorial-atmosphere` layer. The three ways to connect share the top row, and the two authoring cards share the row below. CLI takes rose because it is the recommended path; the others take ember or stone. The mobile menu lists the same five items as a plain group. Harlan asked for this on 2026-10-06. diff --git a/GLOSSARY.md b/GLOSSARY.md index efacd921..1fb55093 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -28,6 +28,7 @@ Shared terms match the skilld CLI glossary (`skilld-dev/skilld/GLOSSARY.md`). Th | skilld token | `cli_tokens`, `layers/identity` | Author 1—N token | "skilld token" | | provenance | Skill detail, cards | Skill 1—1 author and source link | "written by", "source" | | behavior | `skilld-protocol/behaviors`, Skill page | Skill 1—N behavior | "Skill behaviors" | +| Skillgen | `workers/skill-harness`, `/skillgen` | Repository 1—N draft pull request | "Skillgen" | Collisions @@ -240,6 +241,14 @@ Existing route paths, table names, and protocol fields keep their identifiers. **Casing:** lowercase in prose and UI. +### Skillgen + +**Is:** the `skilld-skillgen` GitHub App. After each release tag, it opens a draft pull request that updates a package skill. The maintainer reviews it and decides what merges. + +**Never:** bot (in UI copy), skill generator, auto-update. + +**Casing:** `Skillgen` in prose and UI. `skilld-skillgen` only where GitHub shows the App's name. + ### guide skill **Is:** a curation tag for a Skill not tied to a package. Distributed as a git Skill, tagged for filtering in browse views. diff --git a/app/app.vue b/app/app.vue index 2700d6a8..64b9c320 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,5 +1,7 @@ + + + + diff --git a/app/utils/developer-menu.ts b/app/utils/developer-menu.ts new file mode 100644 index 00000000..060157d9 --- /dev/null +++ b/app/utils/developer-menu.ts @@ -0,0 +1,65 @@ +/** + * The header's Developers menu. Desktop shows each item as a card; the mobile + * menu lists the same items. COPY.md owns every string here. + */ +export interface DeveloperMenuItem { + label: string + description: string + /** The card's call to action. */ + action: string + icon: string + to: string + /** The card's `.editorial-atmosphere` palette. Rose marks the recommended path. */ + palette: 'rose' | 'ember' | 'stone' + /** `connect` cards share the top row; `author` cards share the row below. */ + group: 'connect' | 'author' +} + +export const developerMenuItems: DeveloperMenuItem[] = [ + { + label: 'CLI', + description: 'Search, run, install, and keep Skills current.', + action: 'Install the CLI', + icon: 'i-lucide-square-terminal', + to: '/cli', + palette: 'rose', + group: 'connect', + }, + { + label: 'MCP server', + description: 'For ChatGPT, Claude, and any app that speaks MCP.', + action: 'Add the MCP server', + icon: 'i-lucide-plug', + to: '/developers?setup=mcp', + palette: 'ember', + group: 'connect', + }, + { + label: 'SDK', + description: 'For your own code, with the TypeScript SDK or plain HTTP.', + action: 'Call the skilld API', + icon: 'i-lucide-braces', + to: '/developers?setup=api', + palette: 'stone', + group: 'connect', + }, + { + label: 'Make a skill', + // generate-package-skill, generate-project-skill and review-skill. + description: 'Guides and three authoring Skills to write and review your own.', + action: 'Get the steps', + icon: 'i-lucide-pen-line', + to: '/make-skill', + palette: 'stone', + group: 'author', + }, + { + label: 'Skillgen', + description: 'Keeps your package skill current with a draft pull request after each release.', + action: 'Set up Skillgen', + icon: 'i-lucide-git-pull-request-draft', + to: '/skillgen', + palette: 'ember', + group: 'author', + }, +] diff --git a/layers/marketing/app/pages/skillgen.vue b/layers/marketing/app/pages/skillgen.vue new file mode 100644 index 00000000..0e94e112 --- /dev/null +++ b/layers/marketing/app/pages/skillgen.vue @@ -0,0 +1,131 @@ + + + diff --git a/layers/marketing/app/utils/page-admissions.ts b/layers/marketing/app/utils/page-admissions.ts index 468fb144..c5b2c0c7 100644 --- a/layers/marketing/app/utils/page-admissions.ts +++ b/layers/marketing/app/utils/page-admissions.ts @@ -43,6 +43,7 @@ export const FREEZE_AUDIT_PATHS: readonly string[] = [ '/docs/cli', '/cli', '/developers', + '/skillgen', '/privacy', '/learn/private-repositories', '/learn/create-agent-skills', diff --git a/package.json b/package.json index 1eedaca4..8389cb41 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "nuxt-auth-utils": "catalog:", "nuxt-og-image": "catalog:", "rangi": "catalog:", + "reka-ui": "catalog:", "skilld-protocol": "catalog:", "skilld-sdk": "catalog:", "tailwindcss": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91d683a1..9ad28b1f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -338,6 +338,9 @@ catalogs: rangi: specifier: ^2.2.0 version: 2.2.0 + reka-ui: + specifier: 2.10.4 + version: 2.10.4 skilld-protocol: specifier: ^2.5.0 version: 2.5.0 @@ -496,6 +499,9 @@ importers: rangi: specifier: 'catalog:' version: 2.2.0 + reka-ui: + specifier: 'catalog:' + version: 2.10.4(vue@3.5.43(typescript@6.0.3)) skilld-protocol: specifier: 'catalog:' version: 2.5.0(patch_hash=40578b24b5375959d96e2286d7fdcf6424e9827d7c72c7705df3352dce1c2aac) @@ -2333,15 +2339,9 @@ packages: cpu: [x64] os: [win32] - '@internationalized/date@3.12.3': - resolution: {integrity: sha512-fuLX+3ZKLsxI73y8b01EG/WjHb6gE6weCqlfawPO27kBWGMh9G1yH6Csv1uU7/cac9H2GHmOMt6CjmuQ1aia4Q==} - '@internationalized/date@3.12.4': resolution: {integrity: sha512-M1dEn4c1U1HsSlaVR8upZtSqvXrTkHDfv18H01uCSJyjVLDxnBR38v/fMxecmlwXKR4i9HeZcmgQAPE6A+aGJQ==} - '@internationalized/number@3.6.7': - resolution: {integrity: sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==} - '@internationalized/number@3.6.8': resolution: {integrity: sha512-8UmMFia46DUt+k97zKd9fKWXcWHR+k8ae3eYzILETuT2KbIvLyOfac7zesw+sJdRAAZ7Q9pM1Mk22aXp2LD0Ig==} @@ -4052,20 +4052,12 @@ packages: '@tanstack/virtual-core@3.17.11': resolution: {integrity: sha512-+ILjvtHup6Y2hzQ6YzwMgX1Q+oQpxEGOXCEsCNaPoIP0VxMbizIBTmYTDtkerkIQS8/CbP1BRuyt8V/8BCsy1g==} - '@tanstack/virtual-core@3.17.7': - resolution: {integrity: sha512-bp+v10y65sp2H7WpWfIMyxTNfl8ZVfxFTLRjPIFRryi6FV/J33z4IS53WO4pTk36KlvJ4iLiQz+oaydDC1xbcA==} - '@tanstack/vue-table@8.21.3': resolution: {integrity: sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==} engines: {node: '>=12'} peerDependencies: vue: '>=3.2' - '@tanstack/vue-virtual@3.13.35': - resolution: {integrity: sha512-lOfSPvgPdlaH6Qy+CyIc3XpycitaSQ9GECndGpTuDiu+uDA1am+90yWXwzDSd/20ZM196ggWJLS+Qb6WjVd/OA==} - peerDependencies: - vue: ^2.7.0 || ^3.0.0 - '@tanstack/vue-virtual@3.13.39': resolution: {integrity: sha512-AG8sI+6nfrDvN6ixuHJL9LaJTf3//0V5VITZYW3UOaIuSVexnEzsbMu4LH/JhMfRTxwhUXPnLqkl1DlzkZbRtg==} peerDependencies: @@ -8219,11 +8211,6 @@ packages: resolution: {integrity: sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==} hasBin: true - reka-ui@2.10.3: - resolution: {integrity: sha512-nJGZbwcha8AcP2wbnjodfzsciTKBqp1mIzepC9Pi2xDI/YK3++ej3vpJOSPyxqrkq1Oorj4K+BdJkbVCV6x6ag==} - peerDependencies: - vue: '>= 3.4.0' - reka-ui@2.10.4: resolution: {integrity: sha512-kbS5GAbkHkYj0EVKAg5ZPEPndhBjeUFSa1Aq5m5ftQwyHnB1v5tw8X6fcwfKH/ry3StPXblMWM1DW82MVS71cw==} peerDependencies: @@ -9069,6 +9056,7 @@ packages: vaul-vue@0.4.1: resolution: {integrity: sha512-A6jOWOZX5yvyo1qMn7IveoWN91mJI5L3BUKsIwkg6qrTGgHs1Sb1JF/vyLJgnbN1rH4OOOxFbtqL9A46bOyGUQ==} peerDependencies: + reka-ui: ^2.0.0 vue: ^3.3.0 verkit@0.3.2: @@ -11040,18 +11028,10 @@ snapshots: '@img/sharp-win32-x64@0.35.4': optional: true - '@internationalized/date@3.12.3': - dependencies: - '@swc/helpers': 0.5.23 - '@internationalized/date@3.12.4': dependencies: '@swc/helpers': 0.5.23 - '@internationalized/number@3.6.7': - dependencies: - '@swc/helpers': 0.5.23 - '@internationalized/number@3.6.8': dependencies: '@swc/helpers': 0.5.23 @@ -12147,7 +12127,7 @@ snapshots: unplugin: 3.4.0(esbuild@0.28.2)(rolldown@1.2.4)(rollup@4.62.4)(vite@8.2.1(@types/node@26.4.0)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.50.0)(tsx@4.23.13)(yaml@2.9.1)) unplugin-auto-import: 21.1.0(@nuxt/kit@4.5.2(magic-string@1.2.3)(magicast@0.5.4)(oxc-parser@0.143.0)(rolldown@1.2.4)(unplugin@3.3.0(esbuild@0.28.2)(rolldown@1.2.4)(rollup@4.62.4)(vite@8.2.1(@types/node@26.4.0)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.50.0)(tsx@4.23.13)(yaml@2.9.1))))(@vueuse/core@14.4.0(vue@3.5.43(typescript@6.0.3)))(esbuild@0.28.2)(oxc-parser@0.143.0)(rolldown@1.2.4)(rollup@4.62.4)(vite@8.2.1(@types/node@26.4.0)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.50.0)(tsx@4.23.13)(yaml@2.9.1)) unplugin-vue-components: 32.1.0(@nuxt/kit@4.5.2(magic-string@1.2.3)(magicast@0.5.4)(oxc-parser@0.143.0)(rolldown@1.2.4)(unplugin@3.3.0(esbuild@0.28.2)(rolldown@1.2.4)(rollup@4.62.4)(vite@8.2.1(@types/node@26.4.0)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.50.0)(tsx@4.23.13)(yaml@2.9.1))))(esbuild@0.28.2)(rolldown@1.2.4)(rollup@4.62.4)(vite@8.2.1(@types/node@26.4.0)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.50.0)(tsx@4.23.13)(yaml@2.9.1))(vue@3.5.43(typescript@6.0.3)) - vaul-vue: 0.4.1(vue@3.5.43(typescript@6.0.3)) + vaul-vue: 0.4.1(reka-ui@2.10.4(vue@3.5.43(typescript@6.0.3)))(vue@3.5.43(typescript@6.0.3)) vue-component-type-helpers: 3.3.11 optionalDependencies: valibot: 1.4.2(typescript@6.0.3) @@ -13354,18 +13334,11 @@ snapshots: '@tanstack/virtual-core@3.17.11': {} - '@tanstack/virtual-core@3.17.7': {} - '@tanstack/vue-table@8.21.3(vue@3.5.43(typescript@6.0.3))': dependencies: '@tanstack/table-core': 8.21.3 vue: 3.5.43(typescript@6.0.3) - '@tanstack/vue-virtual@3.13.35(vue@3.5.43(typescript@6.0.3))': - dependencies: - '@tanstack/virtual-core': 3.17.7 - vue: 3.5.43(typescript@6.0.3) - '@tanstack/vue-virtual@3.13.39(vue@3.5.43(typescript@6.0.3))': dependencies: '@tanstack/virtual-core': 3.17.11 @@ -18371,29 +18344,13 @@ snapshots: dependencies: jsesc: 3.1.0 - reka-ui@2.10.3(vue@3.5.43(typescript@6.0.3)): - dependencies: - '@floating-ui/dom': 1.8.0 - '@floating-ui/vue': 1.1.11(vue@3.5.43(typescript@6.0.3)) - '@internationalized/date': 3.12.3 - '@internationalized/number': 3.6.7 - '@tanstack/vue-virtual': 3.13.35(vue@3.5.43(typescript@6.0.3)) - '@vueuse/core': 14.4.0(vue@3.5.43(typescript@6.0.3)) - '@vueuse/shared': 14.4.0(vue@3.5.43(typescript@6.0.3)) - aria-hidden: 1.2.6 - defu: 6.1.7 - ohash: 2.0.12 - vue: 3.5.43(typescript@6.0.3) - transitivePeerDependencies: - - '@vue/composition-api' - reka-ui@2.10.4(vue@3.5.43(typescript@6.0.3)): dependencies: '@floating-ui/dom': 1.8.0 '@floating-ui/vue': 1.1.11(vue@3.5.43(typescript@6.0.3)) - '@internationalized/date': 3.12.3 - '@internationalized/number': 3.6.7 - '@tanstack/vue-virtual': 3.13.35(vue@3.5.43(typescript@6.0.3)) + '@internationalized/date': 3.12.4 + '@internationalized/number': 3.6.8 + '@tanstack/vue-virtual': 3.13.39(vue@3.5.43(typescript@6.0.3)) '@vueuse/core': 14.4.0(vue@3.5.43(typescript@6.0.3)) '@vueuse/shared': 14.4.0(vue@3.5.43(typescript@6.0.3)) aria-hidden: 1.2.6 @@ -19351,10 +19308,10 @@ snapshots: vary@1.1.2: {} - vaul-vue@0.4.1(vue@3.5.43(typescript@6.0.3)): + vaul-vue@0.4.1(reka-ui@2.10.4(vue@3.5.43(typescript@6.0.3)))(vue@3.5.43(typescript@6.0.3)): dependencies: '@vueuse/core': 10.11.1(vue@3.5.43(typescript@6.0.3)) - reka-ui: 2.10.3(vue@3.5.43(typescript@6.0.3)) + reka-ui: 2.10.4(vue@3.5.43(typescript@6.0.3)) vue: 3.5.43(typescript@6.0.3) transitivePeerDependencies: - '@vue/composition-api' diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6946d922..7f4c7e44 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -238,6 +238,9 @@ catalog: nuxt-og-image: ^6.9.1 nuxt-skew-protection: ^1.5.4 rangi: ^2.2.0 + # The header menu imports reka-ui directly. Keep it equal to the version + # @nuxt/ui pins, or the client ships two copies. + reka-ui: 2.10.4 skilld-protocol: ^2.5.0 skilld-sdk: 0.1.2 tailwindcss: ^4.3.3 diff --git a/test/a11y.spec.ts b/test/a11y.spec.ts index 8ba32428..f1e3e0e0 100644 --- a/test/a11y.spec.ts +++ b/test/a11y.spec.ts @@ -548,6 +548,42 @@ describe('accessibility: components', () => { wrapper.unmount() }) + it('headerNavigation opens the Developers panel with no violations', async () => { + const container = createIsolatedContainer() + const wrapper = await mountSuspended( + await loadComponent('_HeaderNavigation'), + { attachTo: container }, + ) + const trigger = wrapper.get('#header-developers-trigger') + expect(trigger.attributes('aria-expanded')).toBe('false') + + await trigger.trigger('click') + await nextTick() + + expect(trigger.attributes('aria-expanded')).toBe('true') + // reka-ui renders an aria-hidden focus proxy after an open trigger. It + // moves focus into the panel as soon as it gets focus, and Shift+Tab skips + // it, so focus never rests there. Only that span leaves the scan. + const results = await axe.run( + { include: [container], exclude: [['[data-navigation-menu-trigger] + span[aria-hidden="true"]']] }, + AXE_OPTIONS, + ) + expect(results.violations, formatViolations(results)).toHaveLength(0) + + // The panel's label points at the fixed trigger id that replaces reka-ui's. + const panel = container.querySelector('[aria-labelledby]')! + expect(container.querySelector(`#${panel.getAttribute('aria-labelledby')}`)).toBe(trigger.element) + expect([...panel.querySelectorAll('a')].map(link => link.getAttribute('href'))).toEqual([ + '/cli', + '/developers?setup=mcp', + '/developers?setup=api', + '/make-skill', + '/skillgen', + '/developers', + ]) + wrapper.unmount() + }) + it('runChip compact has no violations', async () => { const container = createIsolatedContainer() const wrapper = await mountSuspended( From fda6067bb4831b20fbbf39154d1f276eabf6eb36 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Tue, 6 Oct 2026 12:57:53 +1100 Subject: [PATCH 2/4] fix(header): run the panel animation and correct Skillgen setup steps The panel renders through reka-ui's Teleport, so it never carried the scope attribute and its open and close animations never ran. The hover bridge also covered the bottom edge of the other header buttons. On /skillgen, installing before joining the pilot loses the first run, since the Worker drops installs from repositories outside the allowlist. The page now says to join first. The Worker accepts 9 files, not 8. --- COPY.md | 4 +-- app/components/_HeaderNavigation.vue | 36 ++++++++++--------------- layers/marketing/app/pages/skillgen.vue | 15 +++++------ 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/COPY.md b/COPY.md index 1082b165..751dec1b 100644 --- a/COPY.md +++ b/COPY.md @@ -37,7 +37,7 @@ These exact strings. Do not paraphrase them per page. | Home section: trending | Trending skills this week. | guidance only: the homepage trending section heading | | Home section: changes | Keep up with skill changes. | guidance only: the homepage section heading for watching and the digest | | Home section: authoring | Write a skill for your project. | guidance only: the homepage section heading for making a Skill | -| Nav: developers | Developers | guidance only: the header menu trigger, and the group label in the mobile menu. The menu holds the four cards below | +| Nav: developers | Developers | guidance only: the header menu trigger, and the group label in the mobile menu. The menu holds the five cards below | | Nav: CLI | CLI · Search, run, install, and keep Skills current. · Install the CLI | guidance only: the first card in the Developers menu: name, line, action. Links `/cli`. The mobile menu shows the name only. The line is the CLI line and the action is the CLI install label, so change those first | | Nav: MCP server | MCP server · For ChatGPT, Claude, and any app that speaks MCP. · Add the MCP server | guidance only: a Developers menu card. Links `/developers?setup=mcp`. The line is the MCP setup card on `/developers`, and the action is its section heading | | Nav: SDK | SDK · For your own code, with the TypeScript SDK or plain HTTP. · Call the skilld API | guidance only: a Developers menu card. Links `/developers?setup=api`. The line is the API setup card on `/developers`, and the action is its section heading | @@ -45,7 +45,7 @@ These exact strings. Do not paraphrase them per page. | Nav: Skillgen | Skillgen · Keeps your package skill current with a draft pull request after each release. · Set up Skillgen | guidance only: the last Developers menu card. Links `/skillgen` | | Nav: setup guides | All setup guides | guidance only: the link under the Developers menu cards. Links `/developers` | | Skillgen lead | Keep your package skill current. After each release tag, Skillgen opens a draft pull request that updates the Skill in your repository. You review it and decide what merges. | guidance only: the `/skillgen` line under the H1. Its first two sentences are the page's meta description | -| Skillgen pilot | Skillgen is in a pilot. It runs only on repositories in the pilot. | guidance only: the `/skillgen` note while the Worker reads `GITHUB_PILOT_REPOSITORIES`. Remove it when the pilot opens | +| Skillgen pilot | Skillgen is in a pilot. It runs only on repositories in the pilot. Open an issue with your repository to join. Install the App after we add your repository, so its first run starts. | guidance only: the `/skillgen` note while the Worker reads `GITHUB_PILOT_REPOSITORIES`. Remove it when the pilot opens | | CLI H1 | The skilld CLI | guidance only: the `/cli` H1 and its OG title | | CLI line | Search, run, install, and keep Skills current. | guidance only: the `/cli` line under the H1. It is the CLI's own `--help` line, so change it in the CLI first | | CLI intro | Give your Agent Skills that real maintainers write. A run reads the current source every time, and one command updates the Skills you install. Install the skilld Skill once, and your Agent searches and loads Skills on its own. | guidance only: the `/cli` intro under the line | diff --git a/app/components/_HeaderNavigation.vue b/app/components/_HeaderNavigation.vue index 8d134050..45a76a09 100644 --- a/app/components/_HeaderNavigation.vue +++ b/app/components/_HeaderNavigation.vue @@ -26,11 +26,8 @@ watch(() => route.fullPath, () => { route.fullPath, () => { route.fullPath, () => { />
    @@ -138,14 +132,14 @@ watch(() => route.fullPath, () => {