Skip to content

Commit cef0d2b

Browse files
authored
feat(docs): add Copy Prompt button for AI assistants (#1706)
## What Adds a reusable **Copy Prompt** button to the Vite+ docs. It copies a ready-made, AI-friendly getting-started prompt to the clipboard so users can hand it straight to their coding agent. The prompt introduces Vite+, points the agent at `https://viteplus.dev/llms-full.txt`, gives the platform-specific install commands, and lists the core `vp` commands. ## Where it appears - **Front page** — in the hero CTA row, beside *Get started* / *Read the Announcement* (`docs/.vitepress/theme/components/home/Hero.vue`). The row is now `flex-wrap` so three buttons don't overflow on narrow screens. - **Getting Started** — right after the intro paragraph (`docs/guide/index.md`). ## Implementation - New `docs/.vitepress/theme/components/CopyPrompt.vue` — a single themed `.button` with `prompt` / `label` props (defaults to a shared `DEFAULT_PROMPT` and `"Copy Prompt"`). Clipboard + flash-feedback logic models the existing `InstallCommand.vue`; shows **Copied!** on success and **Could not copy** on failure. - Registered globally via `enhanceApp` in `docs/.vitepress/theme/index.ts` so any Markdown page can use `<CopyPrompt />` without an import. - Pointer clicks drop focus so the theme's `outline`-based `.button` border isn't stripped by the global `button:focus:not(:focus-visible) { outline: none !important }` reset — that reset only bites real `<button>` elements, since the theme otherwise uses `.button` on `<a>` tags. Keyboard activation keeps focus so the a11y focus ring still shows. Scope: main `docs/` site only; the duplicate `packages/cli/docs/` guide tree is intentionally left unchanged. ## Verification - `cd docs && pnpm build` — clean production build; the button renders into both `index.html` and `guide/index.html`, and the prompt is bundled. - Previewed in `pnpm dev`: button reads **Copy Prompt**, flashes **Copied!**, and keeps its border through the click on both pages. - Fact-checked the copied prompt end-to-end: both install URLs resolve to the real installers, `llms-full.txt` is live and documents every command named, and a fresh `vp create → install → check → dev → build` workflow all succeed. (`vp test` exits non-zero only because a bare scaffold has no test files yet — expected Vitest behavior.) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent d195acf commit cef0d2b

4 files changed

Lines changed: 107 additions & 1 deletion

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<script setup lang="ts">
2+
import { Icon } from '@iconify/vue';
3+
import { onBeforeUnmount, ref } from 'vue';
4+
5+
// Default getting-started prompt handed to an AI coding assistant. Every
6+
// command and URL here is verified against the Getting Started guide and the
7+
// live llms-full.txt docs dump.
8+
const DEFAULT_PROMPT = `I want to use Vite+ in my project. Vite+ is the unified toolchain for the web behind the \`vp\` CLI — one tool combining Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task, plus runtime and package-manager management.
9+
10+
First, read https://viteplus.dev/llms-full.txt to learn Vite+'s commands and configuration.
11+
12+
Install the \`vp\` CLI:
13+
- macOS / Linux: curl -fsSL https://vite.plus | bash
14+
- Windows (PowerShell): irm https://vite.plus/ps1 | iex
15+
16+
Then open a new terminal and run \`vp help\`. To scaffold a new project run \`vp create\`; to move an existing Vite project onto Vite+ run \`vp migrate\`.
17+
18+
Day-to-day commands: \`vp install\` (dependencies), \`vp dev\` (dev server), \`vp check\` (format + lint + type-check), \`vp test\` (tests), and \`vp build\` (production build).
19+
20+
Help me get set up and explain anything I should know.`;
21+
22+
const props = withDefaults(
23+
defineProps<{
24+
prompt?: string;
25+
label?: string;
26+
}>(),
27+
{
28+
prompt: DEFAULT_PROMPT,
29+
label: 'Copy Prompt',
30+
},
31+
);
32+
33+
const state = ref<'idle' | 'copied' | 'error'>('idle');
34+
let resetTimer: ReturnType<typeof setTimeout> | null = null;
35+
36+
const flash = (next: 'copied' | 'error') => {
37+
state.value = next;
38+
if (resetTimer) {
39+
clearTimeout(resetTimer);
40+
}
41+
resetTimer = setTimeout(() => {
42+
state.value = 'idle';
43+
resetTimer = null;
44+
}, 1600);
45+
};
46+
47+
const copyPrompt = async (event: MouseEvent) => {
48+
// The theme draws the `.button` border with an `outline`, but a global reset
49+
// (`button:focus:not(:focus-visible) { outline: none !important }`) strips it
50+
// after a mouse click. The theme only ever uses `.button` on <a> tags, so this
51+
// bites only real <button> elements. For pointer activation (event.detail > 0)
52+
// drop focus so the button returns to its resting state and keeps its border;
53+
// keyboard activation (detail === 0) keeps focus so the a11y focus ring shows.
54+
if (event.detail > 0) {
55+
(event.currentTarget as HTMLElement | null)?.blur();
56+
}
57+
try {
58+
await navigator.clipboard.writeText(props.prompt);
59+
flash('copied');
60+
} catch {
61+
flash('error');
62+
}
63+
};
64+
65+
onBeforeUnmount(() => {
66+
if (resetTimer) {
67+
clearTimeout(resetTimer);
68+
}
69+
});
70+
</script>
71+
72+
<template>
73+
<button
74+
type="button"
75+
class="button"
76+
:aria-label="`${label} for setting up Vite+ with an AI assistant`"
77+
@click="copyPrompt"
78+
>
79+
<Icon
80+
:icon="
81+
state === 'copied' ? 'lucide:check' : state === 'error' ? 'lucide:x' : 'lucide:clipboard'
82+
"
83+
class="size-4"
84+
aria-hidden="true"
85+
/>
86+
<span>{{ state === 'copied' ? 'Copied!' : state === 'error' ? 'Could not copy' : label }}</span>
87+
</button>
88+
</template>
89+
90+
<style scoped>
91+
.button {
92+
display: inline-flex;
93+
align-items: center;
94+
gap: 0.5rem;
95+
}
96+
</style>

docs/.vitepress/theme/components/home/Hero.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</p>
1313
<p class="text-sm text-grey">Free and open source under the MIT license.</p>
1414
</div>
15-
<div class="flex items-center gap-5">
15+
<div class="flex flex-wrap items-center justify-center gap-5">
1616
<a href="/guide" target="_self" class="button button--primary"> Get started </a>
1717
<a
1818
href="https://voidzero.dev/posts/announcing-vite-plus-alpha"
@@ -22,6 +22,7 @@
2222
>
2323
Read the Announcement
2424
</a>
25+
<CopyPrompt />
2526
</div>
2627
</div>
2728
</div>

docs/.vitepress/theme/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
import BaseTheme from '@voidzero-dev/vitepress-theme/src/viteplus';
33
import type { Theme } from 'vitepress';
44

5+
import CopyPrompt from './components/CopyPrompt.vue';
56
import Layout from './Layout.vue';
67
import './styles.css';
78
import 'virtual:group-icons.css';
89

910
export default {
1011
extends: BaseTheme,
1112
Layout,
13+
enhanceApp({ app }) {
14+
// Globally available so Markdown pages can use <CopyPrompt /> without an import.
15+
app.component('CopyPrompt', CopyPrompt);
16+
},
1217
} satisfies Theme;

docs/guide/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Vite+ is the unified toolchain and entry point for web development. It manages y
44

55
Vite+ ships in two parts: `vp`, the global command-line tool, and `vite-plus`, the local package installed in each project. If you already have a Vite project, use [`vp migrate`](/guide/migrate) to migrate it to Vite+, or paste our [migration prompt](/guide/migrate#migration-prompt) into your coding agent.
66

7+
Building with an AI assistant? Copy a ready-made setup prompt:
8+
9+
<CopyPrompt />
10+
711
## Install `vp`
812

913
### macOS / Linux

0 commit comments

Comments
 (0)