Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions COPY.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ These exact strings. Do not paraphrase them per page.
| 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 page | What /{name} made Β· One recorded run: the prompt, and what the Agent built with the Skill. | guidance only: the H1 and line of a demo page, `/skills/demos/<owner>/<repo>/<name>`. The meta title is "{name} skill example: {noun}" for the query "<skill> skill example", with `noun` from `DEMO_GROUPS`. The meta description is "{agent} made this {noun} with the /{name} skill from one prompt: β€œ{prompt}”", cut at a word to 160 characters |
| 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 |
| Writing demo | Writing Β· Articles, READMEs, and PR descriptions. Β· Files Β· Updated Β· Diff Β· Markdown Β· No newline at end of file | guidance only: writing support on the existing demos board. Show file buttons with Markdown icons and one Diff toggle with an icon. Show the updated document by default. Diff compares the original seed and updated Markdown with line numbers and syntax highlighting. Fit short documents to their content and cap long documents. Keep the no-Skill baseline in recording data for later evaluations. No decorative text. |
| Writing demo example | Example data Β· Example data. No Skills were run. | guidance only: each known writing Skill uses `/skills/demos/<owner>/<repo>/<name>`, with `/{name}` as its heading. All candidate rows share handwritten UI fixtures. Keep the disclosure visible. Show no recording metadata. Reuse the demo footer with Skill links, Run it yourself, and Copy demo link. The run prompt supplies the original fixture documents. README and PR documents use GitHub-style Markdown with the shared Skill renderer and rangi highlighter. Diff toggles the Markdown comparison on and off. |
| Demo actions | Run it yourself Β· Agent prompt Β· Terminal Β· Copy Agent prompt Β· Copy command Β· Copied Β· Copy demo link Β· Copied demo link | guidance only: demo stages. The Agent prompt includes the recorded task. The terminal option loads the Skill. Run is hidden on phones. |
| Demo stage | Open the demo | guidance only: the demo stage link. The hero shows the output, author row, and this link only. On the homepage it opens the demo page; on a demo page it opens the Skill page Demo panel |
| Home demo carousel | Previous demo Β· Next demo Β· {n} of {total} | guidance only: the manual homepage demo controls. The position is live text for screen readers. |
Expand Down
3 changes: 3 additions & 0 deletions GLOSSARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ It grants no trust or search indexing. Existing Skills retain source refresh.

**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.

**Writing:** a demo can show Markdown documents. Each document keeps its original, the rewrite without a Skill, and the Skill output.
UI fixtures are labelled Example data. They are not recorded runs or evaluation results.

### preview

**Is:** the step of watching a Skill's demo before running it. A preview never executes a Skill.
Expand Down
55 changes: 9 additions & 46 deletions app/components/DemoStage.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script setup lang="ts">
import type { HomeDemoItem } from '~/utils/home-demos'
import { demoPagePath } from '#shared/demo-pages'
import { demoCardSkill, demoHasPhoneFrame, demoHref, demoPhoneRatio, demoRecording } from '~/utils/home-demos'
import DemoActions from './_DemoActions.vue'
import { demoHasPhoneFrame, demoHref, demoPhoneRatio, demoRecording } from '~/utils/home-demos'
import DemoFooter from './_DemoFooter.vue'
import DemoMedia from './home-demos/_DemoMedia.vue'
import DemoRecording from './home-demos/_DemoRecording.vue'
import SkillCard from './SkillCard.vue'
import DemoWriting from './home-demos/_DemoWriting.vue'

/**
* One demo on show: how it was recorded, the output in a window one screen
Expand All @@ -32,7 +32,7 @@ const { demo, surface = 'demos', eager = false, showPrompt = false, live = false
const stage = useTemplateRef<HTMLElement>('stage')
const { record } = useDemoEngagement(() => `${demo.owner}/${demo.repo}/${demo.name}`, surface, stage)
const recording = computed(() => demoRecording(demo))
const liveUrl = computed(() => live && !demo.video ? demo.liveUrl : null)
const liveUrl = computed(() => live && !demo.video && !demo.writing ? demo.liveUrl : null)
</script>

<template>
Expand All @@ -59,8 +59,12 @@ const liveUrl = computed(() => live && !demo.video ? demo.liveUrl : null)
<p v-if="showPrompt && presentation === 'full'" class="demo-stage__prompt">
<span class="data-label mr-2">Prompt</span>{{ demo.prompt }}
</p>
<div v-if="demo.writing" ref="stage">
<DemoWriting :writing="demo.writing" />
</div>
<!-- The whole page, in a window one screen tall. A film fills the window and plays on view. -->
<div
v-else
ref="stage"
class="demo-stage__window"
:data-phone="demoHasPhoneFrame(demo) ? '' : undefined"
Expand All @@ -83,21 +87,7 @@ const liveUrl = computed(() => live && !demo.video ? demo.liveUrl : null)
/>
<DemoMedia v-else :demo :eager play="visible" />
</div>
<div class="demo-stage__id">
<SkillCard
:skill="demoCardSkill(demo)"
layout="row"
metric="none"
:description="false"
:actions="[]"
:surface
/>
<NuxtLink v-if="presentation === 'hero'" :to="demoPagePath(demo)" class="demo-stage__open" :aria-label="`Open the demo of /${demo.name}`">
Open the demo
<UIcon name="i-lucide-arrow-right" class="size-3.5 shrink-0" aria-hidden="true" />
</NuxtLink>
<DemoActions v-else :demo :surface @action="record" />
</div>
<DemoFooter :demo :surface :presentation @action="record" />
</div>
</template>

Expand Down Expand Up @@ -176,13 +166,6 @@ const liveUrl = computed(() => live && !demo.video ? demo.liveUrl : null)
aspect-ratio: var(--phone-ratio, 4 / 5);
}

.demo-stage__id :deep(.skill-card--row) {
padding-block: 0.5rem;
}

.demo-stage__id :deep(.skill-card__row-end) {
display: none;
}
}

/* Give interactive pages most of the screen, while keeping their actions in reach. */
Expand All @@ -197,15 +180,6 @@ const liveUrl = computed(() => live && !demo.video ? demo.liveUrl : null)
inline-size: min(100%, calc(68svh * var(--video-w) / var(--video-h)));
}

.demo-stage--compact .demo-stage__id {
position: sticky;
inset-block-end: 0;
z-index: 2;
border-block-start: 1px solid var(--ui-border);
background: var(--ui-bg);
padding-block-end: env(safe-area-inset-bottom, 0px);
}

.demo-stage--compact .demo-stage__head {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
Expand Down Expand Up @@ -268,15 +242,4 @@ const liveUrl = computed(() => live && !demo.video ? demo.liveUrl : null)
outline: 2px solid var(--ui-border-accented);
outline-offset: 2px;
}

/* The Skill row's hover fill follows the rounded corners of everything around it. */
.demo-stage__id {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: 0.5rem;
margin-block-start: 0.25rem;
overflow: hidden;
border-radius: var(--ui-radius);
}
</style>
4 changes: 2 additions & 2 deletions app/components/_DemoActions.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup lang="ts">
import type { HomeDemoItem } from '~/utils/home-demos'
import type { DemoIdentity } from '~/utils/home-demos'
import { demoPagePath } from '#shared/demo-pages'
import { skillPageUrl, skillRunCmd, skillRunPrompt } from '#shared/skill-commands'

const { demo, surface } = defineProps<{ demo: HomeDemoItem, surface: string }>()
const { demo, surface } = defineProps<{ demo: DemoIdentity, surface: string }>()
const emit = defineEmits<{ action: [action: { event: 'share' } | { event: 'copy', format: 'agent' | 'terminal' }] }>()
const format = ref<'agent' | 'terminal'>('agent')
const text = computed(() => format.value === 'agent'
Expand Down
62 changes: 62 additions & 0 deletions app/components/_DemoFooter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang="ts">
import type { DemoIdentity } from '~/utils/home-demos'
import { demoPagePath } from '#shared/demo-pages'
import { demoCardSkill } from '~/utils/home-demos'
import DemoActions from './_DemoActions.vue'
import SkillCard from './SkillCard.vue'

const { demo, surface, presentation = 'full' } = defineProps<{
demo: DemoIdentity
surface: string
presentation?: 'full' | 'hero' | 'compact'
}>()
const emit = defineEmits<{ action: [action: { event: 'share' } | { event: 'copy', format: 'agent' | 'terminal' }] }>()
</script>

<template>
<div class="demo-footer" :class="{ 'demo-footer--compact': presentation === 'compact' }">
<SkillCard :skill="demoCardSkill(demo)" layout="row" metric="none" :description="false" :actions="[]" :surface />
<NuxtLink v-if="presentation === 'hero'" :to="demoPagePath(demo)" class="demo-footer__open" :aria-label="`Open the demo of /${demo.name}`">
Open the demo
<UIcon name="i-lucide-arrow-right" class="size-3.5 shrink-0" aria-hidden="true" />
</NuxtLink>
<DemoActions v-else :demo :surface @action="emit('action', $event)" />
</div>
</template>

<style scoped>
.demo-footer {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: 0.5rem;
margin-block-start: 0.25rem;
overflow: hidden;
border-radius: var(--ui-radius);
}
.demo-footer--compact {
position: sticky;
inset-block-end: 0;
z-index: 2;
border-block-start: 1px solid var(--ui-border);
background: var(--ui-bg);
padding-block-end: env(safe-area-inset-bottom, 0px);
}
.demo-footer__open {
display: inline-flex;
align-items: center;
gap: 0.25rem;
min-block-size: 2.75rem;
margin-inline-start: auto;
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--ui-text);
text-decoration: underline;
text-underline-offset: 4px;
}
.demo-footer__open:hover { color: var(--ui-text-highlighted); }
@media (max-width: 39.99rem) {
.demo-footer :deep(.skill-card--row) { padding-block: 0.5rem; }
.demo-footer :deep(.skill-card__row-end) { display: none; }
}
</style>
Loading
Loading