diff --git a/COPY.md b/COPY.md
index 672cbd1b..9f4f6c00 100644
--- a/COPY.md
+++ b/COPY.md
@@ -39,8 +39,12 @@ These exact strings. Do not paraphrase them per page.
| Agents way: terminal | From a terminal · Teaches your agent to search and run Skills in every project. | guidance only: the second way, over `npx skilld install skilld --global` |
| Agents way: MCP | In ChatGPT, Claude, and other MCP apps · Add the server once. Then ask the chat to find a Skill. | guidance only: the third way, over the MCP server URL. Its link, "Setup steps for each app", opens `/developers?setup=mcp` |
| Home section: demos | See what skills make. · Each demo is one recorded run: the prompt, and what the Agent built with the Skill. | guidance only: the homepage demo section heading and line. The section hides below three demos |
+| Nav: demos | Skill Demos | guidance only: the header link after Trending Skills, and the same item in the mobile menu. Links `/skills/demos` |
+| Demos link | All {n} demos | guidance only: under the homepage demo section. Links `/skills/demos` |
+| Demos page | See what skills make · Each demo is one recorded run: the prompt, and what the Agent built with the Skill. Pick a prompt to see the output, or open it live. | guidance only: the `/skills/demos` H1 and line. The meta title is "Claude skill examples: see what each one makes" for the admitted query |
+| Demo groups | Films and launch videos · Landing pages · UI components · Diagrams and explainers | guidance only: `DEMO_GROUPS` in `shared/demo-groups.ts`: the `/skills/demos` group headings and their lines |
| Demo stage | Open the demo | guidance only: the homepage demo stage link to the Skill page Demo panel |
-| Demo panel | Demo · You say · Open live demo · Open in a new tab · Run it yourself | guidance only: the Skill page Demo panel. "Show screenshots" replaces "Open live demo" while the live output shows |
+| Demo panel | Demo · Prompt · Open live demo · Open in a new tab · Run it yourself | guidance only: the Skill page Demo panel. "Show screenshots" replaces "Open live demo" while the live output shows |
| Demo provenance | {Agent logo} {model}, such as Opus 5.5 | guidance only: the recording line on the Skill page panel and the homepage stage. Screen readers and the title get "Recorded with {agent}, {model}". No date and no GitHub link: the Skill page is where visitors inspect a Skill |
| Demo outdated | Recorded on an older version of this Skill. | guidance only: under the Demo panel when the Skill moved past the recorded commit |
| Home section: changes | Keep up with skill changes. | guidance only: the homepage section heading for watching and the digest |
diff --git a/GLOSSARY.md b/GLOSSARY.md
index 3a991e98..f2f78383 100644
--- a/GLOSSARY.md
+++ b/GLOSSARY.md
@@ -94,6 +94,8 @@ Collisions
**Rule:** a demo shows the Agent's output, never the Skill author's work. It always names how it was recorded.
+**Groups:** demos group by what the Skill makes, on `/skills/demos`: films and launch videos, landing pages, UI components, and diagrams and explainers. A group is not a track: tracks sort Skills by kind of work.
+
### install
**Is:** `skilld install`. Skill files land in the project and the lockfile records them. The opt-in second step.
diff --git a/app/app.vue b/app/app.vue
index 64b9c320..cbcd246b 100644
--- a/app/app.vue
+++ b/app/app.vue
@@ -177,6 +177,14 @@ watch(() => route.fullPath, () => {
Trending Skills
+
+import type { HomeDemoItem } from '~/utils/home-demos'
+import { githubAvatarProxyUrl } from '#shared/image-proxy'
+import { demoKey } from '~/utils/home-demos'
+import { resolveAuthorName } from '~/utils/skill-byline'
+import DemoStage from './DemoStage.vue'
+
+/**
+ * Demos as a prompt index. The prompts are the menu: pick one and the stage
+ * shows what the Agent made from it, scrollable to the end of the page, or its
+ * film playing. Each prompt carries a stone dot, and the picked one turns rose.
+ * On a phone the stage opens under the picked prompt.
+ */
+const { demos, initialKey, surface = 'demos' } = defineProps<{
+ demos: HomeDemoItem[]
+ /** `owner/repo/name` of the demo to show first, such as one from a shared link. */
+ initialKey?: string
+ /** The analytics surface for the run chip, such as `home-demos`. */
+ surface?: string
+}>()
+
+const emit = defineEmits<{ pick: [demo: HomeDemoItem] }>()
+
+const stageId = useId()
+
+const picked = ref(Math.max(0, demos.findIndex(demo => demoKey(demo) === initialKey)))
+const current = computed(() => demos[Math.min(picked.value, demos.length - 1)])
+
+function pick(index: number): void {
+ picked.value = index
+ const demo = demos[index]
+ if (demo)
+ emit('pick', demo)
+}
+
+function author(demo: HomeDemoItem): string {
+ return resolveAuthorName(demo.owner, demo.authorName) ?? demo.owner
+}
+
+
+
+
+
@@ -75,285 +27,17 @@ const [DefineStage, ReuseStage] = createReusableTemplate<{ demo: HomeDemoItem, e
Each demo is one recorded run: the prompt, and what the Agent built with the Skill.
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
diff --git a/app/components/_HeaderNavigation.vue b/app/components/_HeaderNavigation.vue
index 2a05761c..a53c7691 100644
--- a/app/components/_HeaderNavigation.vue
+++ b/app/components/_HeaderNavigation.vue
@@ -42,6 +42,18 @@ watch(() => route.fullPath, () => {
+
+
+
+
+ formatDemoDuration(video.durationSeconds))
inset: 0;
inline-size: 100%;
block-size: 100%;
- object-fit: cover;
+ /* The frame already matches the film, so nothing is cropped or stretched. */
+ object-fit: contain;
object-position: center;
}
diff --git a/app/utils/home-demos.ts b/app/utils/home-demos.ts
index bbe08534..c28e9270 100644
--- a/app/utils/home-demos.ts
+++ b/app/utils/home-demos.ts
@@ -1,3 +1,4 @@
+import type { DemoMakes } from '#shared/demo-groups'
import type { SkillCardSkill } from '~/types/skill-card'
import { demoAgentIcon, demoModelLabel } from '#shared/demo-recording'
@@ -10,6 +11,8 @@ export interface HomeDemoItem {
repo: string
name: string
skillPath: string
+ /** What the Skill made: the demo's group on `/skills/demos`. */
+ makes: DemoMakes
/** The Skill author, and the SKILL.md in their Repository (VISION principle 1). */
authorName: string | null
sourceUrl: string | null
@@ -21,6 +24,8 @@ export interface HomeDemoItem {
recordedAt: string
shots: { src: string, width: number, height: number, alt: string, viewport: 'desktop' | 'mobile' }[]
/** A Skill whose output is a film. The poster is a JPG frame; `src` is a muted H.264 MP4. */
+ /** The sandboxed output page of a page demo; null for a film. */
+ liveUrl: string | null
video: HomeDemoVideo | null
}
diff --git a/layers/marketing/app/pages/skills/demos.vue b/layers/marketing/app/pages/skills/demos.vue
new file mode 100644
index 00000000..f90993c0
--- /dev/null
+++ b/layers/marketing/app/pages/skills/demos.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+ See what skills make
+
+
+ Each demo is one recorded run: the prompt, and what the Agent built with the Skill.
+
+
+
+
+
+
+
+
+
+
+
+
+ No demos are published yet.
+
+
+
+
+
+
diff --git a/layers/marketing/app/utils/page-admissions.ts b/layers/marketing/app/utils/page-admissions.ts
index c5b2c0c7..7fa1d897 100644
--- a/layers/marketing/app/utils/page-admissions.ts
+++ b/layers/marketing/app/utils/page-admissions.ts
@@ -53,9 +53,14 @@ export const FREEZE_AUDIT_PATHS: readonly string[] = [
'/learn/author-ruby-package-skills',
'/learn/author-rust-package-skills',
'/learn/author-go-package-skills',
+ '/skills/demos',
]
export const PAGE_ADMISSIONS: Readonly> = {
+ '/skills/demos': {
+ targetQuery: 'claude skills examples',
+ admissionBar: '720 searches a month, KD 32. NuxtSEO research keywords, 2026-10-06. Holds only demos a human approved by merging, and renders noindex below six. Review at the 2026-11-11 gate.',
+ },
'/compare/humanize-writing-skills': {
targetQuery: 'best humanizer skill for claude',
admissionBar: 'Experiment F, owner-approved 2026-10-05: one original source comparison with contextual internal links. Query estimate: 30 US searches a month, below the volume bar. Retain admission at the 2026-11-11 gate only if indexed with relevant query impressions.',
diff --git a/layers/registry/app/components/_SkillDemo.vue b/layers/registry/app/components/_SkillDemo.vue
index 8c6377ca..4edab881 100644
--- a/layers/registry/app/components/_SkillDemo.vue
+++ b/layers/registry/app/components/_SkillDemo.vue
@@ -32,7 +32,7 @@ const live = ref(false)
- You say{{ demo.prompt }}
+ Prompt{{ demo.prompt }}
Folder{{ demo.setup }}
@@ -57,6 +57,7 @@ const live = ref(false)
playsinline
preload="none"
class="skill-demo__video"
+ :style="{ maxInlineSize: `${demo.video.width}px` }"
:aria-label="`Video the Agent rendered with ${demo.name}`"
>
@@ -137,10 +138,12 @@ const live = ref(false)