Skip to content
Draft
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 bolt-slides/.bolt/prompt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Import project modules with the `@/` path alias, which maps to `src/` (e.g. `@/components/Foo` == `src/components/Foo`), instead of deep relative paths like `../../components/Foo`.

This template uses Vite 8. `resolve.tsconfigPaths: true` is a valid built-in Vite option. Preserve it for the `@/` alias; do not claim it is invalid or add the `vite-tsconfig-paths` plugin.

Author decks by writing `deck.json` and `src/styles/tokens.css`. Follow `.bolt/skills/slides/SKILL.md`. Layout `props` match `src/data/layoutProps.ts`.
485 changes: 174 additions & 311 deletions bolt-slides/.bolt/skills/slides/SKILL.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions bolt-slides/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ lerna-debug.log*
node_modules
dist
dist-ssr
.vite
*.local

.vscode/*
Expand All @@ -21,3 +22,5 @@ dist-ssr
*.sln
*.sw?
.env

public/og.png
76 changes: 49 additions & 27 deletions bolt-slides/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,58 @@
# Bolt slides skill
# Bolt Slides

A Bolt skill that builds a premium, **responsive React presentation deck** — classic
paged slides you present one at a time, with a Slidev-style floating dock + thumbnail
rail, grid overview, click-builds, annotation, and presenter mode — but each slide is a
responsive web layout (no fixed canvas, no clipping) built from a rich component
library.
A Pitch-style slide studio for [Bolt](https://bolt.new): prompt a deck into
`deck.json`, refine it in the studio, present in a new tab, and
download PDF or JSON.

## The skill
The prompt skill (`.bolt/skills/slides/SKILL.md`) covers bootstrap
(mint `boltSlidesId` on first write) and authoring. Layout `props`
shapes live in `src/data/layoutProps.ts`.

This repo **is** the running app. The authoring guide lives at
[`.bolt/skills/slides/SKILL.md`](./.bolt/skills/slides/SKILL.md); the app itself sits
at the repo root — a complete Vite + React deck: the paged engine + chrome
(`src/deck/`), fourteen slide layouts (`src/components/`: Cover, BigNumber,
Contrast, Chat, Globe, Bento, Split, StatGrid, Section, Quote, Pricing, Steps,
Agenda, Team) plus a dozen building blocks (Table, Comparison, Tabs, Accordion, Timeline,
CodeWindow, BrowserFrame, SpotlightCard, charts, CountUp, TiltCard, Marquee, …),
and the token-driven theme (`src/styles/`). The engine is left as-is; only the
`:root` token block and the slides in `src/App.tsx` are authored per deck.
## Quick start

## Add it in Bolt
```bash
npm install
npm run dev # studio at http://localhost:5173 — Present opens a new tab
npm run lint # ESLint (same kit as bolt-vite-react-ts)
npm run typecheck
```

1. In Bolt's **Add skill from GitHub**, paste this repo's URL —
`https://github.com/inkko44/bolt-slides-skill`.
2. The `slides` skill auto-discovers at `.bolt/skills/slides.md`.
3. Tell Bolt to use the `slides` skill and build a deck about your topic/brand.
Prompt a deck with the `slides` skill, or edit `deck.json` directly.
In the studio, drag to reorder, use a thumbnail’s ••• menu (or
right-click) to duplicate or delete, edit speaker notes, then Present
or Download as PDF / JSON.

## Run it locally
## What's inside

```bash
npm install
npm run dev
- `/` — In Bolt this is the studio: canvas, side panel (S), grid (G),
and a floating dock (pager, notes, Download, Present, Presenter).
Present opens `/?present=1` in a new tab; the studio stays put.
Fullscreen is F in that tab. The published origin is the audience
deck. **P** opens the presenter console in a second tab.
- `/?presenter=1` — Presenter console: on-screen now, up next, notes
(read-only), timer, note text size. `/present` is the same route.

Collaborate by sharing the Bolt project.

## The skill

`.bolt/skills/slides/SKILL.md` covers bootstrap (mint `boltSlidesId` on
first write) and authoring `deck.json` plus `src/styles/tokens.css`.
Layout `props` shapes live in `src/data/layoutProps.ts`.

## Architecture

```
deck.json canonical deck (envelope + slides)
src/data/ types, layout props contract, zustand store
src/layouts/ layout registry
src/components/ section components
src/deck/ presentation engine
src/edit/ studio chrome
src/styles/tokens.css theme: edit :root values only
```

`npm run dev` opens the deck at `/`. Re-theme everything by editing one `:root` block
in `src/styles/tokens.css`.
## Theming

Everything visual derives from the `:root` tokens in `src/styles/tokens.css`.
`--accent` must stay a solid color.
79 changes: 79 additions & 0 deletions bolt-slides/deck.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"boltSlidesVersion": 1,
"deck": {
"title": "Slides",
"transition": "fade"
},
"slides": [
{
"id": "s1",
"position": 0,
"layout": "cover",
"props": {
"kicker": "Company · 2026",
"title": "A ==bold== opening.",
"subtitle": "One sharp sentence on what this deck argues.",
"foot": "August 2026 · Your name"
},
"background": { "type": "color", "color": "var(--bg)" },
"animation": "cascade",
"transition": null,
"nav": null,
"notes": "Open with the one-line promise of the deck.",
"status": "none"
},
{
"id": "s2",
"position": 1,
"layout": "statement",
"props": {
"kicker": "",
"title": "Say the ==one thing== this slide exists to say.",
"body": ""
},
"background": { "type": "color", "color": "var(--bg)" },
"animation": "cascade",
"transition": null,
"nav": null,
"notes": "Land the thesis. Pause before you click on.",
"status": "none"
},
{
"id": "s3",
"position": 2,
"layout": "bigNumber",
"props": {
"kicker": "The market",
"value": "$3T",
"caption": "moves through this problem every year",
"foot": "Source: —"
},
"background": { "type": "color", "color": "var(--bg)" },
"animation": "cascade",
"transition": null,
"nav": null,
"notes": "Give the figure a beat, then say what it means for us.",
"status": "none"
},
{
"id": "s4",
"position": 3,
"layout": "agenda",
"props": {
"kicker": "Agenda",
"title": "What we'll cover.",
"items": [
{ "title": "The problem", "hint": "5 min" },
{ "title": "The product" },
{ "title": "The ask" }
]
},
"background": { "type": "color", "color": "var(--bg)" },
"animation": "cascade",
"transition": null,
"nav": null,
"notes": "Preview the arc so they know where this is going.",
"status": "none"
}
]
}
34 changes: 34 additions & 0 deletions bolt-slides/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
/* Layout catalogs export schema + Render functions, not Fast Refresh
boundaries. Same kit as bolt-vite-react-ts otherwise. */
{
files: ['src/layouts/**/*.{ts,tsx}'],
rules: { 'react-refresh/only-export-components': 'off' },
}
);
17 changes: 11 additions & 6 deletions bolt-slides/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Always replace the title + favicon emoji to match the deck topic -->
<title>Replace — your deck title</title>
<link
rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎞️</text></svg>"
/>
<title>Slides</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 178 227'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M103.267 198.762C87.1743 198.762 71.3565 192.914 62.2897 180.315L59.0909 195.151L0 226.551L6.37813 195.151L49.3961 0H102.089L86.8603 68.7856C99.1455 55.3229 110.567 50.3381 125.208 50.3381C156.823 50.3381 177.901 71.121 177.901 109.174C177.901 147.227 153.605 198.742 103.247 198.742L103.267 198.762ZM123.461 120.321C123.461 138.474 110.587 152.231 93.9056 152.231C84.5445 152.231 76.0469 148.718 70.493 142.576L78.6963 106.564C84.8389 100.421 91.8646 96.9083 100.068 96.9083C112.647 96.9083 123.48 106.269 123.48 120.321H123.461Z' fill='%231688FC'/%3E%3C/svg%3E" />
<meta name="theme-color" content="#05070a" />
<!-- OpenGraph — og.png is generated from slide 1 -->
<meta property="og:title" content="Slides" />
<meta property="og:description" content="A deck built with Bolt Slides." />
<meta property="og:type" content="website" />
<meta property="og:image" content="/og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="/og.png" />
</head>
<body>
<div id="root"></div>
Expand Down
Loading
Loading