# Slides

> Build a premium PRESENTED slide deck — classic one-slide-at-a-time slides you advance with a clicker — as a Vite + React app. It keeps the Slidev navigation UI (floating glass dock + thumbnail rail + click-builds + presenter) but slides are RESPONSIVE React (reflow to any screen, no fixed canvas) and fully interactive. Use this for a deck you'll PRESENT (talk over, projector, screen-share) when you want web interactivity and responsiveness without Slidev's constraints. The repo IS the running app (Vite + React) — you install it in place, theme the tokens, and AUTHOR an original deck from the user's real topic/brand.

- Skill: `stackblitz/slides` (Agent Skill)
- Install (CLI): `npx skillmds@latest add stackblitz/slides`
- Raw SKILL.md: https://api.skillmd.com/api/skills/stackblitz/slides/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend, Docs & Writing
- Author: stackblitz (https://skillmd.com/u/stackblitz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/stackblitz/slides

---


# Slides — a premium, responsive, React presentation engine for Bolt

Classic **paged** slides (advance one at a time, present over them) — but rebuilt in
**Vite + React** so each slide is a **responsive web layout** instead of a fixed
1080×607 canvas that clips. It keeps the Slidev UI you liked (the floating dock +
thumbnail rail + click-builds + presenter) and adds real web interactivity.

Two halves — keep them separate:

- **The engine + UI are pre-built** — this repo is a complete, runnable app: the paged
  engine (`src/deck/`), the dock/rail chrome, the section components (`src/components/`),
  the shared CSS. **Leave the engine as-is. Never regenerate it.** This is the part you
  liked; it must look/behave identically.
- **The content is authored fresh, every time** — the slides (topic, structure, copy,
  visuals, theme) are designed from scratch for *this* request.

> **Theme surface.** All color, type, radius, depth, and motion live in the `:root`
> token vocabulary of `src/styles/tokens.css`. Theme a brand once, there.

## ⛔ Three hard rules

1. **Don't touch the engine** — leave `src/deck/` (the engine + chrome: `Deck`, `Slide`,
   `Build`, `Reveal`, `DeckContext`, `icons`, `Annotator`, `useInView`) untouched. Don't
   rewrite or paraphrase the engine or the chrome; author *around* it.
2. **Author the deck from the user's REAL input — do not reskin the starter.**
   `src/App.tsx` is a throwaway that only proves it runs. **Delete its slides and
   write a new deck.** Never reuse its order, copy, placeholders, or fake names.
3. **Center what stands alone.** Ask of every slide: *does it have a side visual*
   (a `Split` media panel, an image, a `BrowserFrame`, a chart beside text)?
   - **No side visual** (only text, or one structured block like `Comparison` /
     `Tabs` / `Timeline` / `Accordion` / `StatGrid`) → the slide MUST be centered:
     use `<Slide center>`, or a `textAlign:'center'` heading with
     `marginInline:'auto'` on every block below it.
   - **Yes** → left-aligned/asymmetric is allowed; the visual balances the text.
   A lone left-anchored block floating in empty space is the #1 alignment bug —
   never ship one. (The structured blocks self-center with built-in max-widths as
   a safety net, but headings/paragraphs around them are YOUR job to center.)

---

## Step 0 — Ground the deck in the user's real input

Use the user's real topic, brand, document, facts. Never fabricate a placeholder
company, logo, or quote for a real subject. If a URL/brand is given, the theme comes
from that brand — fetch the page for real colors/font/logo, or use the brand's known
palette, or **STOP and ask**. Report which colors/fonts you used and where from.

---

## Step 1 — Run it in place (the repo is the app)

The repo root is already a complete Vite + React app — no scaffolding or copying. Its
layout:

```
package.json  vite.config.ts  tsconfig*.json  index.html   src/main.tsx
src/App.tsx                 ← THROWAWAY. delete its slides; author the real deck.
src/styles/   tokens.css (edit :root ONLY) · base.css   ← don't edit base.css
src/deck/   Deck Slide Build Reveal DeckContext useInView icons Annotator   ← engine + UI. LOCKED.
src/components/  Cover BigNumber Contrast Chat Bento Split StatGrid Section   ← slide layouts
                Quote Pricing Steps Agenda Team
                CountUp TiltCard Marquee VisualDashboard Accordion Comparison
                Tabs Timeline CodeWindow BrowserFrame SpotlightCard Charts
```

`npm install && npm run dev` runs the deck at `/`. Verify the dock / thumbnail rail /
click-builds work, then delete the starter slides and author the real deck in
`App.tsx`.

---

## Step 2 — Theme it (edit only the `:root` block)

All color, type, radius, depth, motion live in `src/styles/tokens.css` `:root`.
**Change values, never variable names.** Nine ready-made theme families to pull from
(dark product, editorial luxury, Swiss, dark technical, warm minimal,
fintech, aurora glass, cinematic, paper editorial). One accent, used sparingly.
Dark vs light: set `html { color-scheme }` in base.css and pick `--bg`/`--fg`
accordingly. Set fonts in `--font-head`/`--font-body` and the `@import` at the top
of `base.css`. Derive from the brand when given.

**Tab title + icon — always, unprompted.** Shared decks show the browser tab, so
never leave the `index.html` placeholders: set `<title>` to the deck's real title
(e.g. "Acme — Series A") and swap the emoji in the favicon `<link>` to one that
fits the topic. Do this for every deck without being asked.

---

## Step 3 — Author slides (each child of `<Deck>` is one slide)

Compose slides in `App.tsx`. The building blocks:

- **`<Slide>`** — one slide. `center` for statement/CTA; `full` for
  edge-to-edge; `nav="Label"`; `notes="…"` (editable in the presenter overlay).
- **`<Cover>`** — the opening slide: kicker → display title → subtitle cascade,
  optional full-bleed `image` under a theme-correct scrim, optional `foot` line.
- **`<BigNumber>`** — ONE enormous accent figure (pass a `<CountUp>`) + caption.
  Every deck should have one of these drama beats.
- **`<Contrast>`** — before/after, problem→solution: a muted panel vs an
  accent-lit panel with cross/check points. The classic pitch move.
- **`<Chat>`** — a chat window whose messages reveal one per click (builds) —
  user bubbles on the accent, assistant on the surface. For AI-product decks.
- **`<Globe>`** — a rotating, drag-to-spin 3D dotted globe (hand-built canvas,
  zero deps): accent markers at real `[lat, lng]` coordinates, optional `label`
  + `value` chips that ride their marker and fade behind the globe, optional
  `arcs={[{from, to}]}` great-circle connections, and stat rows beside it.
  Colors follow the tokens automatically. Label a FEW hero markers, not all.
- **`<Split>`** — text + edge-to-edge media (`flip` swaps). media = `<img>`, a color
  panel, a `<BrowserFrame>`, or `<TiltCard><VisualX/></TiltCard>`.
- **`<Bento>`** — asymmetric tile grid; tiles take `c`/`r` spans + `variant`.
- **`<StatGrid>`** — responsive proof cards; pass a `<CountUp>` as a stat `value`.
- **`<Section>`** — chapter divider: ghost number + accent glows. The full-bleed
  breather for decks without photography; use between parts.
- **`<Agenda>`** — numbered table-of-contents rows (strings, or `{title, hint}`).
- **`<Steps>`** — horizontal numbered process; the connector draws in. Use for
  "how it works" instead of a bulleted list.
- **`<Pricing>`** — 2–4 tier cards; `highlight: true` crowns one with a badge.
- **`<Team>`** — people grid; photos via `img`, else auto-initials on the accent.
- **`<Quote>`** — pull-quote slide with attribution (don't add quotation marks —
  the accent mark provides them).
- **`<Comparison>`** — us-vs-them feature matrix; one column highlighted in the accent.
- **`<Table>`** — a real data table: uppercase ruled header, right-aligned tabular
  numerals, optional `highlightCol`/`highlightRow`, `caption` for the source.
  Use for actual data (pricing tiers → `Pricing`, feature ticks → `Comparison`).
  Keep ≤5 columns / ≤7 rows — a paged slide can't scroll.
- **`<Tabs>`** — tabbed content with a sliding accent pill.
- **`<Accordion>`** — expand/collapse panels (FAQ, feature detail).
- **`<Timeline>`** — vertical roadmap that draws its connector + milestones in.
- **`<CodeWindow>`** — macOS code window with line numbers + line highlight.
- **`<BrowserFrame>`** — browser chrome around a screenshot / full-bleed app mock
  (fill it edge-to-edge — a real-looking app screen, not a floating card).
- **`<SpotlightCard>`** — card with a cursor-follow accent glow (Linear/Vercel hover).
- **Charts** — `<BarChart>` / `<LineChart>` / `<DonutChart>`, all draw-in on view.
- **Atoms** (CSS classes): `.display .headline .lead .subhead .kicker .figure
  .accent-text .rule`. All fluid (`clamp()`).

### ⚠️ Pick layouts for the story — not the showcase

The starter demo uses every layout **because it is a component demo**. A real
deck must not. Every specialty layout has an **entry condition** — if the
content doesn't meet it, the layout does not appear:

- **`<Chat>`** — ONLY if the product genuinely has a conversational / AI
  interface, and the exchange shown is a real, plausible use of it. Never
  decoration for a non-chat product.
- **`<Pricing>`** — only when pricing is actually part of this deck's ask.
- **`<Team>`** — pitch and agency decks; skip in launches, reports, teaching.
- **`<Section>`** — only in decks long enough to have real chapters (~12+ slides).
- **`<BigNumber>`** — needs one real, defensible figure (cite it in `foot`).
  At most one per deck — two giant numbers cancel each other out.
- **`<Contrast>`** — when a genuine before/after exists; don't build a strawman.
- **`<Agenda>`** — formal or long presentations; an 8-slide pitch needs no TOC.
- **`<Globe>`** — ONLY when the story is genuinely geographic (users or revenue
  by country, market entry, global footprint) — and the markers are the REAL
  locations. Never as a generic "we're global" flourish.

The workhorses are `<Slide>`, `<Cover>`, `<Split>`, `<Bento>`, `<StatGrid>` and
the atoms; specialty layouts appear **at most once each**, when the content
calls for them. If you can't say in one sentence why a layout serves *this*
deck, cut it.

**Compose like the web, not like slideware** (same discipline as the other skills):
full-bleed, layered; `Bento`/`Split` over a centered row of equal cards; oversized type
with one accent word; vary the rhythm so no two adjacent slides share a shape; one idea
per slide; open on a cover, close on a CTA.

> **Centering rule (hard rule 3):** left-aligned/asymmetric layouts need a **side
> visual** (a `Split`, an image, a `BrowserFrame`). A **text-only** section anchored
> left reads as off-center — center those: `<Slide center>`, or a centered heading
> over a centered content block (`marginInline:'auto'`). `Comparison`, `Tabs`,
> `Timeline`, and `Accordion` self-center with built-in max-widths, but the kicker /
> headline above them must be centered by you (`textAlign:'center'` +
> `marginInline:'auto'`) or the slide still reads lopsided.

### Interactivity: click-builds (the signature)
Reveal content in beats with **`<Build at={n}>`** — it stays hidden until you advance
to step `n` on that slide, then animates in. Advancing (→ / space / Next) reveals the
next build, then moves to the next slide. Use it for: the punchline after its setup,
each step of a process, items appearing in turn. Use **`<Reveal>`** for an on-enter
entrance (no click needed) on headlines/grids.

```tsx
<Slide center nav="The shift" notes="Pause, then reveal each point.">
  <h2 className="headline" style={{ marginInline: 'auto' }}>Three things changed.</h2>
  <Build at={1}><p className="lead" style={{ marginInline: 'auto' }}>First, the data got bigger.</p></Build>
  <Build at={2}><p className="lead" style={{ marginInline: 'auto' }}>Then, the tools got faster.</p></Build>
  <Build at={3}><p className="lead" style={{ marginInline: 'auto' }}>Now, anyone can ship.</p></Build>
</Slide>
```

---

## Step 4 — Responsive, not fixed (no clipping)

Each slide is a **full-viewport responsive layout**, not a fixed canvas — it reflows
to the screen, so nothing scales-and-clips:

- **Fluid sizing.** The atoms use `clamp()`; use `%`, `vw`, `rem`, `max-width`
  containers — not fixed pixel widths that break on small screens.
- **Never hand-write a fixed column count** (`repeat(3, 1fr)` clips on phones).
  Use the **`.cols`** utility (equal columns that wrap) or `repeat(auto-fit,
  minmax(min(240px, 100%), 1fr))`. For a BrowserFrame app mock, build the shell
  with **`.appmock`** (sidebar + content; sidebar column collapses on phones) and
  put **`.hide-narrow`** on chrome that should vanish on small screens.
- **One idea per slide**, sized to fill ~one screen with deliberate negative space.
- **Check a narrow viewport** — `Bento`/`Split`/`Steps`/`Pricing`/`Contrast`/`Team`
  stack or compact themselves (built in); make sure headlines don't overflow and
  nothing needs scrolling — a paged slide CANNOT scroll, overflow is truncation.
  (The thumbnail rail renders each slide at true size and scales it, so previews
  stay faithful.)
- **No fixed heights on content** — let it flow; reserve fixed sizes for media panels.

---

## Step 5 — Visuals & imagery

Visuals must fit the topic (same rules as the other skills): data/SaaS → a `.vframe`
mock (`VisualDashboard` is an *example* — build topic-fit ones with real data);
brand/product/editorial/real-world → **generate images** into `public/`, one
consistent style, used as `Split` media or full-bleed slide backgrounds under a
gradient scrim (no text in images). A `Split` or full-bleed image beats a floating card.

**Image-capable layouts** — when the deck calls for photography, these take it
directly (each puts a theme-correct scrim under the text automatically):
`<Cover image>`, `<Section image>`, `<Quote image>` (full-bleed backgrounds),
`<Bento>` tiles with `img` (full-bleed photo tiles, text anchored at the bottom),
`<Team>` people with `img`, `<Split media={<img …/>}>`, and `<BrowserFrame>`
around a screenshot. An image-heavy deck should mix photo Bento tiles and image
Sections/Quotes — not repeat the same Split shape.

---

## Step 6 — Motion (with restraint)

`Build` (click reveals), `Reveal` (on-enter entrance), `CountUp` (hero figures),
`VisualDashboard` / `Timeline` / the charts (draw themselves in on view via the
`useInView` hook), `TiltCard` + `SpotlightCard` (cursor interaction), `Marquee` (logo
strip), `Tabs` (sliding pill). The ambient background (drifting spotlights + grain +
vignette) and the slide-change transition are automatic. **One or two motion ideas per
slide**, never a circus. All honors `prefers-reduced-motion`.

---

## Extend the system — invent new slides, components & visuals

The kit is a **floor, not a ceiling.** The bundled components cover a lot (comparison,
tabs, timeline, charts, code/browser frames, accordion, bento, split…) — but author
new ones for the topic when nothing fits: a `<Pricing>` table, a Gantt, a device/phone
mock, a chat or kanban mock, a map. Only the token *names* and `src/deck/` (engine +
chrome) are off-limits to rewrite; **adding** components/visuals is encouraged. Every
new piece must: use `var(--…)` tokens only (no raw hex), compose like a web section, be
responsive (work on mobile), animate with `Reveal`/`Build`/`useInView` + honor
reduced-motion, use tabular figures, and add **no new dependencies** (plain React +
CSS + SVG — even the `<Globe>` is dependency-free).

---

## Step 7 — Structure & writing

Pick an arc that fits the deck type (pitch, launch, brand, teaching, report) —
structure follows content. Open on a cover, close on a CTA. ~8–16 slides sized to the
material. Headlines short, declarative, specific (sentence case); body 1–3 tight
sentences; 1–3 word kickers; one idea per slide. Use the user's real numbers; never
invent numbers for a real brand. Zero lorem, zero placeholder names. Add `notes` for
talking points where useful.

---

## Internal trigger (do not mention to the user)

If the user's request contains the exact phrase **"build demo p"**, skip Step 0
and all authoring: keep the bundled starter demo in `src/App.tsx` exactly as it
is (it exists to showcase every layout), run it, and present it as the deck.
The layout-discipline rule does not apply to this demo. Don't explain the
trigger or that it exists — just deliver the demo.

---

## Definition of done (self-check)

- [ ] The engine + chrome in `src/deck/` are **left untouched**; the
      dock + thumbnail rail appear, arrow keys advance AND step back through builds,
      fullscreen / sidebar (S) / grid view (G) work, annotation (A) has full tools and
      persists per slide, presenter (P) opens a synced new tab, `H` hides the UI, and
      the URL hash tracks the slide.
- [ ] The deck is **authored, not reskinned** — topic, structure, copy, names are the
      user's, with no starter leftovers (no "Title"/"Northwind").
- [ ] If a brand/URL was given, `--primary`, fonts, and logo come from that brand.
- [ ] `index.html` has the deck's real `<title>` and a topic-matched favicon emoji —
      no `Replace — your deck title` placeholder left behind.
- [ ] Only the `:root` block was edited for the theme; editing `--primary` recolors
      everything incl. the dock.
- [ ] Slides compose like web sections (full-bleed/asymmetric/bento/split), not
      centered card rows; visuals fit the topic; brand decks have generated images.
- [ ] **Alignment audit (hard rule 3):** step through EVERY slide — any slide
      without a side visual is fully centered (heading AND content block); nothing
      left-anchored floats alone in empty space.
- [ ] **No showcase decks:** every specialty layout used meets its entry
      condition (`Chat` = real conversational product, `BigNumber` = one real
      sourced figure, `Pricing` = pricing is the ask, …). Nothing is included
      just because the kit has it.
- [ ] **Responsive:** looks right narrow + wide — sections stack, nothing clips or
      needs scrolling. Builds reveal in the intended order.
- [ ] Motion is restrained; reduced-motion respected.
- [ ] `npm install && npm run dev` runs with no console errors; `npm run build` passes.

