Writing a deck

English · Deutsch · 简体中文 · 繁體中文

A deck is good when two things hold: the shape of each slide’s content matches its template, and every field stays inside that template’s content limits. Work through the steps below in order.

Template details are in components.md (generated; currently Chinese only) and in skills/slidehtml/references/templates.md.

1. Collect facts with sources

List every number, date, name and quote you plan to use together with where it comes from (document plus section, e.g. “Release notes §4.3”).

  • No source, no fact. If you are unsure, drop the slide.
  • Estimates and illustrative figures must say so in source (“estimate”, “illustrative”).
  • Never invent testimonials, logos or awards.
  • Every slide that shows data or facts fills in source. Cover and Closing have no source field: any fact on the cover must reappear with a source on a later slide; the refs of Closing are its sources.
  • Things that change over time (“ended”, “N months left”) belong in Timeline’s today and countdowns, not hard-coded text.

2. Write the storyline

First write the one sentence the audience should remember. It becomes the statement of the final Closing slide.

Then order the slides:

  • short: 6–8 slides (under 5 minutes),
  • full: 10–14 slides,
  • long, in chapters: 20–30 slides, each chapter opening with SectionBreak or ChapterProgress.

For each slide, write one sentence saying what it proves. That sentence is usually the title.

3. Match the content shape to a template

Don’t pick a pretty template and stuff it. Decide the shape of the content first, then look in the matching group of the template reference and read its “good for / avoid” lines.

Content shapeLook at
One number carries the slideBigStat, NumberOpener, CountCompare (before/after), Gauge (vs target)
3–4 parallel numbersKpiBoard, StatRow, SparkCards (each with history)
Share of a wholeDonut, Pictogram (n out of N), Waterfall (breakdown of change)
Ranking or change over timeBarChart, MetricBars, LineChart, SlopeRank (rank at two points)
Two things comparedContrast, BeforeAfter, DuoCards, CompareTable, Balance, DoubleFunnel
Ordered stepsStepTrack, ServiceIndex, WindowStack, Swimlane (across roles)
Structure and relationsPyramid, Concentric, ArchLayers, Venn, Orbit
Causes and decisionsIssueTree, Fishbone, DecisionTree, Matrix, Quadrant
Time and plansTimeline, Milestones, Roadmap, Gantt
3–9 parallel pointsIconGrid, TileWall, NumberedColumns, Bento
One sentence or quoteStatement, QuoteHero, QuoteArc (three sourced quotes)
PacingSectionBreak, Teaser, Question, Recap

Rules:

  • Use a template at most twice per deck (SectionBreak once per chapter doesn’t count); Bento at most once.
  • Never use the same template on two adjacent slides.
  • Style-specific templates (e.g. FloatCover, Desktop, KeyReveal) belong in their own style; their “good for” line names it.
  • If nothing fits, change the content to fit a template: split, merge or take another angle. Don’t invent a layout.

4. Fit the text to the limits

Check each field against its template’s limit while you write. Limits are hard: exceeding them breaks the layout.

  • Counting: one CJK character is 1 unit; two Latin letters, digits or spaces are 1 unit. Fields measured in “characters” count every character as 1.
  • Titles state a claim, not a topic: “Runs offline from a single file”, not “Build output overview”. Max 16 units.
  • A title that needs two lines is passed as an array: title={['Ship one page,', 'on a solid base']}. Don’t leave one or two words alone on the second line.
  • kicker names the topic in 2–8 units. lead is one or two sentences (≤ 60 units) adding evidence or context; it never repeats the title.
  • Numbers carry units and scope (“over 14,116”, ”≈ 20%”, “planned date”).
  • Commands, file names and long identifiers go into monospace fields such as cmd, mono, tag or source, not body text.
  • Avoid filler words (“seamless”, “next-level”, “empower”). Use concrete nouns and numbers.
  • Call one concept by one name throughout.
  • If it doesn’t fit, split the slide. Never shrink fonts, never write custom CSS.
  • Columns differ by at most one item. Don’t leave the lower half of a slide empty (add an optional block or use a denser template).

5. Choose a style and theme

DeckDef.style sets title typography, corner radius, paper colour and decoration. DeckDef.theme sets the accent colour. They combine freely, and neither changes the content limits. Compare all styles at #/kit/styles; the full list with descriptions is in skills/slidehtml/references/styles.md.

OccasionStyles
Formal reportsstandard (default), editorial, calm
Launches and brandkeynote, toy3d, poster, gradient, warm-dark, nuance, agency, halo, electric
Products and toolsstudio-dark, bento, soft-saas, float-ui, wallpaper, desktop
Casual talkssticker, playful, pop, ribbon, mono-studio

Themes: crimson (default), amber, cobalt, emerald, violet. Each theme also tints the paper colours. Never hard-code colours in a deck.

Dark and accent slides (tone) are described in presenting.md › Tone.

6. Write the deck file

npx slidehtml new <name> creates src/decks/<name>/index.tsx from the starter. A deck looks like this:

// src/decks/q3-review/index.tsx
import type { DeckDef } from '../../kit'
import { Cover, StatRow, Closing } from '../../kit'

export const deck: DeckDef = {
  title: 'Q3 Platform Review',      // shown top-left on every slide, ≤ 32 characters
  theme: 'cobalt',
  style: 'bento',
  iconStyle: 'line-duotone',        // default; also bold-duotone, linear, outline, broken, bold
  slides: [
    { id: 'cover', label: 'Cover', render: () => <Cover … /> },
    { id: 'numbers', label: 'Scale', build: 'reveal', notes: 'Pause after the second number.',
      render: () => <StatRow … source="Q3 report §2" /> },
    { id: 'end', label: 'Close', tone: 'dark', render: () => <Closing … /> },
  ],
}
  • id is unique, lowercase letters and hyphens. label is short (shown in the header and progress tooltip).
  • Compose only templates from src/kit. Don’t modify templates, don’t write colours or CSS.
  • Icons: only names from src/kit/icon-set.ts (browse at #/kit/icons). Choose by meaning, don’t repeat an icon on one slide, and always put a title next to it.
  • Images: see the image rules in the project README. Use WebP, ≤ 200 KB, about 1440–1600 px wide; set ratio to the real aspect ratio.
  • build, notes, tone, texture and transition are explained in presenting.md.

7. Check and review the screenshots

npx slidehtml check q3-review
  1. The last line must be PASS. Fix every FAIL (see below). Also look at WARN lines such as “lower half looks empty”.
  2. Open every qa/slide-NN-1920x1080.png: too much empty space, an overcrowded slide, no clear focus, one or two words alone on a line.
  3. Emphasis must match the text: if the slide says “longest”, the longest bar is highlighted; if it says “we are at step 3”, only three steps are filled.

Done means PASS and every screenshot reviewed.

Emoji

Type an emoji in any text field of any format: deck, report, résumé, card, video, course or screen. No template needs changing. Each one is drawn from a set bundled with slidehtml, so it looks the same on every machine and in every export. Only the emoji you use go into the file.

export const deck: DeckDef = { title: '…', emojiStyle: 'fluent', slides: [ … ] }
emojiStyleLookUse it for
fluent (default)Soft and dimensionalScreens, cards, video, ordinary PDFs
flatFlat colour, small filesSmall sizes, large print
notoRound and friendlyLarge print

To put one emoji somewhere on its own, or at a set size, use <Emoji e="🚀" size={64} /> from the kit. Cards have a sticker cover: motif: { kind: 'emoji', e: '🎤', around: ['✨', '💡'] }. Add ?emoji=noto to a preview URL to compare families. Browse and search the whole set at #/kit/emoji in the dev preview.

Limits:

  • Country flags and skin-tone variants are not bundled. Using one stops the build with a message naming it.
  • Chart labels drawn as SVG text cannot hold an image, so an emoji there fails QA. Put it in the title or the body instead.
  • In a PDF, fluent emoji become 300 ppi images because they use blur effects. That is sharp at text sizes. flat and noto stay vector, so use one of those for anything printed large.

Use them sparingly: one or two on a slide, in the place you want remembered, and in front of the words rather than in place of them. Keep them out of financial results, legal documents and incident notices. A social card can carry more.

Fixing QA errors

QA checks every slide at 1920×1080, 1366×768, 2560×1440 and 1440×900. Details are in qa/report.json.

ErrorCauseFix
text "…" outside the safe areaText leaves the canvas safe areaShorten to the template’s limit, or use fewer lines/items
text collision: "A" × "B"Two texts overlapFind A in the deck and shorten that field. Usual causes: a long title wrapped (split it with an array), long identifiers in body text (move to tag), too many items in a column
… clips contentContent cut off by its containerShorten that field
font … too smallCustom font sizeRemove the custom style
font … not loaded, boxes instead of charactersNew characters missing from the font subsetRun check again; it re-subsets fonts first
external requests …Remote resource referencedRemove remote images, fonts or links to assets
navigation: …An element intercepts navigation keysDon’t listen to global key events
Type error … not assignable to type IconNameUnknown icon nameLook it up at #/kit/icons