The whole architecture of a deck-as-code framework lives in one type:
interface SlideDefinition {
id: string
title: string
component: ComponentType
controls?: ComponentType
context: SlideContext
}A deck is SlideDefinition[]. A viewer is <DeckViewer slides={SLIDES} />. That's the thesis.
One viewer, many decks
In nopoint, the same DeckViewer renders the YC pitch deck, the information memorandum, a conference talk and a demo-day 2-minute pitch. The component does not know which deck it's showing. It knows how to render slides, navigate between them, manage state, and export them. The deck identity lives in the registry.
// slides/index.ts (pitch deck)
export const SLIDES: SlideDefinition[] = [
TitleSlide,
ProblemSlide,
SolutionSlide,
WhyNowSlide,
ProductSlide,
MarketSlide,
TractionSlide,
WhyWeWinSlide,
BusinessModelSlide,
TeamSlide,
AskSlide,
]// app/pitchdeck/page.tsx
import { DeckViewer } from "@/components/deck-viewer"
import { SLIDES } from "@/components/pitchdeck/slides"
export default () => <DeckViewer slides={SLIDES} storagePrefix="pitchdeck" />That's the entire page. To make a second deck, copy the file, point at a different registry, change the storage prefix.
Adding a slide is import + push
The reason this matters is the iteration loop. In PowerPoint, "add a slide" is "drag a thumbnail and rebuild it." In a registry, it's:
slides/new-slide.tsx— write the JSX.slides/index.ts— import it, push into the array.- Done. It appears in the viewer, the manager, the grid view, the scroll view, and the PDF export.
Reordering is array reordering. Disabling is array.filter. Audience-specific decks are slicing the array. Versioning the deck is committing the file.
Why the type has four fields
Each one earns its place.
id— used for URL state (?slide=problem), localStorage keys, andkeyprops during rendering. The id is human-readable so a shared link is legible.title— for the navigation pills, the deck manager, and the PDF metadata. Decoupled from the component's internal headline so the nav label can be short.component— the slide itself. Standard React. Can use any library, animate, fetch live data, contain another deck if you're feeling ambitious.controls?— optional. A second component that renders next to the slide in non-production mode. Lets a slide ship with its own tunable controls. (Covered in Live-tunable slides.)context— metadata about why the slide exists. Loaded into a sidebar widget at runtime, and read by Claude Code when it edits the slide. (Covered in Every slide carries its rationale.)
That's it. No heavyweight slide engine. No layout DSL. No bullet-point schema. The component is whatever you write.
What the viewer gives you
Because the registry shape is uniform, the viewer can do work on top of it:
- Keyboard navigation (
←/→,Space,V/G/S/Ffor view modes) - A drag-reorder drawer (
M) - Live grid and scroll views that render real
<SlideComponent />s, not screenshots - URL state sync (
?slide=problem&view=grid) - localStorage persistence per
storagePrefix - A full-deck PDF export that walks the registry and rasterises each slide
You write zero of that infrastructure. You write slides.
Deck-type templates
The "deck type" maps to: a registry + a chrome config. Pitch deck has a CONFIDENTIAL watermark and a contact card. Conference talk doesn't. Demo Day strips out the Why-Now and Business Model slides. A customer-facing product narrative hides Ask and financials.
In nopoint these are templates: --type=pitch, --type=im, --type=demo-day, --type=narrative. Each scaffolds a registry and a config. Same viewer underneath.
The line that matters
The registry is the deck. Everything else — view modes, exports, navigation, persistence — is shared infrastructure that doesn't change between decks. If you've spent ten years building slides, you've spent ten years also rebuilding that infrastructure inside whichever slide tool you used. You can stop now.
nopoint gives you the infrastructure. You bring the registry.
Read next
- A slideshow is a website with a PDF export — the first-principles thesis
- Every slide carries its rationale — what
SlideContextis for - Variants in the tree — keeping multiple layouts of the same slide alive