decktalk init writes a deck that already builds, and copying one of its pages is the shortest route
to a second one. This guide is for the other case: a page written from an empty file, because the
deck belongs to a design that neither packaged example fits.
Everything here is the same contract the starter obeys. A [data-scene] wrapper is one scene, each
<template data-slide> inside it is one slide, an element has four moments and each moment is a
cue name. No attribute says when a cue fires, because cues.json owns that.
The skeleton
deck/mine.html
?scene=1, and
records under the cue times a run resolves.
Loading the runtime and KaTeX
DeckTalk serves two things itself, under/__decktalk/ on the origin it opens every page at:
decktalk-runtime.js, the compiled runtime, and katex/, a pinned KaTeX release with its stylesheet
and its font files. Both come from the installed engine, so the project holds no copy of either.
Load them with the absolute paths above, which resolve the same from any directory a page sits in.
KaTeX goes before the runtime, so the first slide is already typeset when the recorder starts the
clock. The runtime waits for a typesetter a page asks for, and a page with data-tex on it and no
KaTeX at all earns PAGE_KATEX_MISSING. A page with no
equations needs neither line.
The canvas
The runtime builds a canvas element,#dt-canvas, of the frame’s shape with a short side of 1080 CSS
pixels, 1920 by 1080 for a wide project, and scales it to fit the window. It puts the canvas’s size on
:root as --dt-width and --dt-height and its shape as data-dt-shape, so a stylesheet that reads
them lays the page out for a square or vertical frame as well. A page that declares its own <div id="dt-canvas"> keeps that element and the runtime
builds around it, which is how a deck puts one background under all of its slides. Style it, and do
not size it.
The scene wrapper
deck/mine.html
data-scene is the id a [[section]] in decktalk.toml names in its scene key. data-name is the
scene’s name in the index page and in the catalog, and a scene with no name is called “Scene” and its
id.
A wrapper holding no <template data-slide> is PAGE_SCENE_EMPTY.
A moment attribute written on the wrapper itself, outside every template, has no slide to qualify it,
so it is PAGE_MOMENT_UNKNOWN.
The slide templates
A slide is a<template> the runtime clones when the slide mounts. Four attributes belong to it.
deck/mine.html
data-enter="cut" where the picture changes completely, because a crossfade there reads as a
dissolve rather than as a new idea. data-describe on the template is the slide’s own subject, and
data-describe on an element inside it is that element’s.
Four rules the reader checks before a pixel is drawn.
- A template inside a scene with no
data-slideisPAGE_SLIDE_NO_ID. - Two templates claiming one id give every moment inside either of them two owners, which is
PAGE_SLIDE_DOUBLED. - A template nested inside a slide with no
data-slideof its own is never mounted, which isPAGE_TEMPLATE_IGNORED. - A slide no recorded section ever mounts is
PAGE_SLIDE_UNUSED.
The DeckTalk object
decktalk-runtime.js publishes window.DeckTalk, which is everything a page may call. A page written
only in markup calls none of it.
window.__decktalk is the same page read back: the mode, the scene, the slide, the cues, the
warnings and the measured catalog. The recorder and every check read the page through it, and a page
never writes to it.
A cue a handler serves
deck/mine.html
DeckTalk.on takes a cue id, because a handler may be registered anywhere in the deck
and nothing around the call says which slide it means. A slide’s own owns and on keys are cue
names, because the slide they belong to already says which slide that is.id, the cue id of the cue, at, the second on the page clock, frozen, whether the page is a
still, and slideId. A handler that throws earns
PAGE_HANDLER_THREW, and the moment does nothing rather
than the page failing.
List in data-owns every cue a handler serves that no moment attribute names. That is what makes
the slide the owner of the cue, and ownership is what decides when the slide is mounted. A cue in
cues.json that no slide owns is PAGE_NO_OWNER, and a cue that
fires and finds neither a moment nor a handler is
PAGE_CUE_UNKNOWN.
A slide built in code
DeckTalk.scene declares a scene whose slides build their own markup. A scene declared in script and
a [data-scene] wrapper with the same id are one scene, so a deck may be half markup and half code,
and a slide that defines render keeps it rather than taking the markup of a template with its id.
deck/mine.html
render returns the slide’s inner HTML and is given the scene, the slide and whether the page is
frozen. It throws into PAGE_RENDER_THREW, entered throws
into PAGE_ENTER_THREW and a handler in on throws into
PAGE_SLIDE_HANDLER_THREW, and in every case the
slide is drawn as its markup stands rather than the page failing.
Waiting for something of your own
deck/mine.html
DeckTalk.waitFor holds the page’s readiness until the promise settles, so the recorder does not
start the clock on a page that is still loading. The budget is five seconds. A promise that rejects
is PAGE_WAIT_REJECTED, one that never settles is
PAGE_WAIT_UNSETTLED, and the page is drawn either way, so
a missing file never hangs a build.
The query keys the runtime reads
One URL decides which of four things the page is doing: it lists its scenes, it previews one, it plays one against the section clock, or it freezes one slide. The query keys lists every key and what it asks for.after and before are answered by the probe that decktalk check and decktalk storyboard inject
into the page. A page you open yourself with ?freeze=1.1 freezes that slide with every one of its
cues fired, and a cue those two keys name that the slide does not declare is
PAGE_FREEZE_CUE_UNKNOWN on the page’s own console.
No command reports it, because storyboard draws a panel only for a cue the slide declares.
Open the page yourself
The recorder opens every page over http, anddecktalk serve is the one supported way to open it
yourself.
file:// URL draws nothing. The browser resolves /__decktalk/decktalk-runtime.js
against the root of the disk, finds no file there, and the page has no runtime to mount its slides.
It serves the deck directory and the files decktalk.toml declares, and nothing else. It prints
where the deck is served as one object, flushed at once, and then serves until you stop it. Its
output stays open while it serves, so a caller reads the object as it arrives rather than waiting for
the stream to end. --host and --port choose the interface and
the port, and a port of 0 takes any free one.
The deck directory is every directory a page sits in, so every name under it is served however the
page spells it. A file outside it, such as a clip, a words file or a sound, is served only by the
spelling decktalk.toml gives it. Write the same name in the page, down to its case, because a
request for Media/Intro.mp4 is refused when the project declared media/intro.mp4, on every
platform alike. The recorder opens the page under the same rule, so a page that previews cleanly
records cleanly.
Open the page by its path under that origin, such as http://127.0.0.1:56257/deck/mine.html:
- The page with no query lists every scene and every slide, and links a preview and a still of each.
deck/mine.html?scene=1previews that scene. Oncedecktalk cuehas run, the preview asks the origin for the cue times that run resolved and plays the film’s own timing. With none to find, it fires each cue a second apart so a deck whose cues have never been resolved still shows its whole self.deck/mine.html?scene=1&speed=4&hud=1reviews a long scene quickly with the clock and the cue list on screen.deck/mine.html?freeze=1.1freezes one slide with its cues fired.
Put the page in the project
decktalk.toml
[[section]] names and the slide ids of its cues agree, which is
the shape every DeckTalk project follows. Then write the section’s narration in script.md and one
row per moment in cues.json, and judge the three together:
Next
- Make each reveal survive a check: Design a slide
- Copy a pattern that already ships: Slide recipes
- Look up every attribute and finding: run
decktalk schema page