mdeck 3.10.1 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +15 -4
  3. package/assets/base.css +6 -1
  4. package/docs/reference/authoring.md +111 -9
  5. package/docs/site/assets/site.css +2 -0
  6. package/docs/site/content/appearance.md +1 -1
  7. package/docs/site/content/audience.md +36 -8
  8. package/docs/site/content/commands.md +6 -3
  9. package/docs/site/content/drawing.md +5 -5
  10. package/docs/site/content/getting-started.md +2 -32
  11. package/docs/site/content/install.md +49 -0
  12. package/docs/site/content/media.md +20 -1
  13. package/docs/site/content/presenting.md +67 -9
  14. package/docs/site/content/sharing.md +1 -0
  15. package/docs/site/content/welcome.md +21 -1
  16. package/docs/site/content/writing.md +27 -0
  17. package/docs/site/images/features/hotspots.webp +0 -0
  18. package/docs/site/images/features/languages.webp +0 -0
  19. package/docs/site/pages.js +1 -0
  20. package/examples/custom-layouts/slides.md +21 -9
  21. package/examples/showcase/refs.bib +21 -0
  22. package/examples/showcase/slides.ar.drawings.json +11 -0
  23. package/examples/showcase/slides.ar.md +567 -0
  24. package/examples/showcase/slides.de.drawings.json +11 -0
  25. package/examples/showcase/slides.de.md +567 -0
  26. package/examples/showcase/slides.de.results.json +57 -0
  27. package/examples/showcase/slides.en.drawings.json +11 -0
  28. package/examples/showcase/{slides.md → slides.en.md} +112 -5
  29. package/package.json +1 -1
  30. package/skills/write-slides/SKILL.md +14 -2
  31. package/src/build/check.js +34 -7
  32. package/src/build/components.js +5 -3
  33. package/src/build/config.js +2 -0
  34. package/src/build/homePlugin.js +64 -14
  35. package/src/build/include.js +249 -0
  36. package/src/build/inkPlugin.js +12 -2
  37. package/src/build/relayAccess.js +3 -1
  38. package/src/build/renderCheck.js +23 -3
  39. package/src/build/slidesPlugin.js +70 -22
  40. package/src/build/svgCheck.js +65 -0
  41. package/src/build/timingPlugin.js +96 -0
  42. package/src/cli/args.js +6 -5
  43. package/src/cli/index.js +77 -21
  44. package/src/components/Bibliography.jsx +7 -2
  45. package/src/components/Poll.jsx +2 -2
  46. package/src/components/QrCodeTag.jsx +2 -2
  47. package/src/components/VideoPlayer.jsx +6 -1
  48. package/src/components/WordCloud.jsx +7 -6
  49. package/src/components/activity.jsx +11 -8
  50. package/src/components/poll.css +2 -0
  51. package/src/core/editDeck.js +44 -7
  52. package/src/core/icons.js +9 -1
  53. package/src/core/labels.js +78 -0
  54. package/src/core/parseSlides.js +16 -6
  55. package/src/core/reactions.js +27 -0
  56. package/src/core/resultsReport.js +153 -0
  57. package/src/core/source.js +8 -1
  58. package/src/core/timing.js +83 -0
  59. package/src/core/validateDeck.js +11 -2
  60. package/src/editor/components/DeckSettings.jsx +1 -0
  61. package/src/editor/components/MetaFields.jsx +1 -0
  62. package/src/home/Home.jsx +39 -93
  63. package/src/home/home.css +5 -17
  64. package/src/layouts/layoutApi.jsx +51 -8
  65. package/src/layouts/renderSlide.jsx +13 -1
  66. package/src/live/answer/answer.css +9 -0
  67. package/src/live/answer/answer.js +32 -4
  68. package/src/live/client.js +23 -4
  69. package/src/live/rooms.js +18 -6
  70. package/src/runtime/KeyHelp.jsx +115 -0
  71. package/src/runtime/PresenterChrome.jsx +168 -0
  72. package/src/runtime/Reactions.jsx +56 -0
  73. package/src/runtime/RehearsalSummary.jsx +129 -0
  74. package/src/runtime/component.js +27 -0
  75. package/src/runtime/deck-stage.js +371 -37
  76. package/src/runtime/helpKeys.js +75 -0
  77. package/src/runtime/ink/bus.js +13 -5
  78. package/src/runtime/ink/outbox.js +27 -0
  79. package/src/runtime/ink/room.js +37 -12
  80. package/src/runtime/ink/segments.js +21 -0
  81. package/src/runtime/main.jsx +508 -286
  82. package/src/runtime/shared.js +77 -0
  83. package/src/runtime/slideControls.js +60 -0
  84. package/src/runtime/steps.js +36 -0
  85. package/src/runtime/useTalkTimer.js +67 -0
  86. package/examples/citations/refs.bib +0 -30
  87. package/examples/citations/refs.yml +0 -21
  88. package/examples/citations/slides.md +0 -43
  89. package/examples/citations/slides.pdf +0 -0
  90. package/examples/poll/slides.md +0 -127
  91. package/examples/showcase/slides.drawings.json +0 -11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.12.0 — 2026-10-12
4
+
5
+ - In a word cloud each phone counts with one word: a new one replaces its earlier word, and the phone says which it sent. Before, one phone could fill the cloud.
6
+ - The poll server says which mdeck it runs (`/info`), and the presenter view warns in amber when your server runs an older mdeck than your computer, whose phones may then miss what is new, such as reactions.
7
+ - With `MDECK_SERVER` and `MDECK_SERVER_KEY` set in your shell, `mdeck run` uses your server without `--server` whenever it answers, and presents from this computer when it does not. `--no-server` leaves it out.
8
+ - The presenter view, redesigned: one toolbar of icons under the slide (each says what it does and its key; **?** lists all keys), with **This slide** for what can be done on the slide shown: a poll's lock, results and right answer, a video's play, the hotspots' numbers. Beside the slide: the slide number, the timer, the next slide small, and the notes in most of the room. Who is connected sits behind the icons that show it, with the audience window and the codes that pair an iPad or a phone; theme, palette, language, layout, rehearsal and the size of the notes are in the settings. The iPad's bar and the phone clicker use the same buttons.
9
+ - A phone becomes a clicker: in the presenter view's connections, **Phone clicker** shows its code. The phone gets the slide small, the time, the notes in large print, big Previous and Next buttons and the slide's own controls, and nothing to draw with. Every layout, the clicker too, switches to the others in the settings. Pairing moved from the launch page into the presenter view.
10
+ - Questions no longer show a QR code of their own: **J**, or the join button in the presenter view, shows the join code large over the slide on every screen, also in a deck window. `qr` on a question still puts the code beside it, and `qr="false"` is no longer needed.
11
+ - **J** shows the join code large over the slide on every screen, so a deck needs no extra join slide. The join link, the session code and whether phones can reach the poll server moved from the launch page into the presenter view's connections.
12
+ - Components can offer their own buttons in the toolbar and on the clicker with `data-presenter-control` (see the authoring reference).
13
+ - The laser has a laser-pointer icon instead of a crosshair, and the presenter view shows mdeck's icon in its tab.
14
+ - **B** makes the audience's screen black: the audience window, a paired iPad's audience window and phones following the talk go black, while the presenter view keeps the slide under a veil and says so. **B** again, the next key or a click on the black screen shows the slide again without moving on. A presentation clicker's blank button, which sends a full stop, works the same. The presenter view has a button for it.
15
+ - **O** shows every slide in a grid, to find one: arrows move between the slides, Enter or a click goes there, **O** or Escape go back. The slides show all their points. In the presenter view the grid opens in the presenter's own slide, so the audience keeps its slide until another is picked; the deck window's control bar has a button for it too.
16
+ - Reactions: with `reactions: true` in the deck's settings, the phones' answer page has a row of buttons (👍 👏 ❤️ 😮 🤔 🐢, or a list of the deck's own, up to eight emoji or short words). A tap floats up in the corner of the presenter view, never on the projector, and a tally keeps the last minute's. The server passes reactions on without keeping them, with a limit of their own, so a room full of reactions behind one network address still gets its answers in. `mdeck check` reports a `reactions` setting it cannot use.
17
+ - The answers kept in a talk can be saved from the launch page: **Answers from the talk** lists each question with how it came out, and saves every answer (CSV), a summary with one row per option, scale step, number or word and how many chose it (CSV), or everything (JSON). `mdeck results` now names each answer's slide, kind and question (`slide,room,kind,question,phone,at,answer`), and takes `--summary` and `--json`.
18
+
19
+ - `<bibliography keys="smith2020 doe2019" />` lists only these works.
20
+ - A deck can be made of other decks. A slide with nothing but `:::include ./lectures/02-graphs.md` stands for all the slides of that file, and `slides=3-7` keeps some of them. The included file stays a deck of its own, presented alone with its own settings. Included, its slides bring what they need: its references (`bibliography`, `nocite`, `csl` where the deck has none), its components, its own callout names (its `<bibliography />` lists the works it cites, as when it is shown alone), and its `hotspots` and `time`, which become its slides' own, shared out as when it is shown alone; the look stays the including deck's. Its pictures and drawings are found from its own folder, a deck in another language takes the file's twin in that language, and includes may nest. `mdeck run` shows a change to an included file straight away, rehearsal times are saved into the file a slide is written in, drawings stay with included slides however the deck around them changes, and `mdeck check` checks every file and names the file and line of a problem. The editor shows an include as a card naming the file; its slides are edited in that file.
21
+ - The number keys are for hotspots only. Without hotspots on the slide shown, they no longer jump to slides 1–10; they do nothing. To go to a slide, type its number into the presenter view's slide number.
22
+ - **?** shows the keys that work at this moment, over the slide in a see-through layer, in the presenter view and in a deck window: the number keys only while the slide shown has hotspots, the drawing keys while drawing, **L** only for a talk in several languages, **N** only in the slide-only layout, **F** only where the browser can go full screen. The list follows along while it is open (press **H** and it changes); **?** again, Escape or a click closes it. In the presenter view, **?** works while the slide has the keyboard too.
23
+
24
+ ## 3.11.0 — 2026-10-12
25
+
26
+ - Time your talk. `time: 2m` in a slide's settings is how long to spend on it, `time: 20m` in the deck's the length of the talk; slides without a time share what is left. The presenter view counts down the time left on the slide and shows whether you are ahead of or behind the plan. `mdeck rehearse` (or **Rehearse** in the presenter view and on the launch page) times each slide as you go through the talk; at the end a table offers the times rounded to 15 seconds, to change in 15-second steps, and **Save to deck** writes them into the slides' settings without reloading the open windows. The editor has a Time field for each slide and a Length for the deck, and `mdeck check` reports a time it cannot read.
27
+ - Under `mdeck run`, the presenter view has a button back to the launch page.
28
+ - The presenter view's timer reads the clock instead of counting seconds, so it no longer falls behind, and carries on through a reload. **T** starts and pauses it.
29
+ - mdeck's own words come in Arabic too: with `lang: ar`, or a file named `talk.ar.md`, the reader view, the control bar, polls, the phones' answer page and callout titles are Arabic.
30
+ - Fixed on slides set from right to left: a palette-coloured drawing (an SVG mdeck places in the page) had its text run out of its box, and a citation in Latin script, such as (Roediger & Karpicke, 2006), was jumbled where it met Arabic text. Drawings now keep their own direction, and citations and references read in theirs.
31
+ - The tour comes in English, German and Arabic (`examples/showcase/slides.en.md`, `.de.md`, `.ar.md`), each with its drawings in place; `mdeck run slides.en.md` switches between them with **L**. It now also shows citations and a word cloud for the room; the poll and citations examples it replaces are gone.
32
+ - Fixed: on a slide with several areas (`:::slot`), a code block in one area turned the next area into code: its citations and footnotes showed as written, while those inside the code block were filled in. Citations and footnotes now leave code blocks and `inline code` alone, and the areas after one are prose again.
33
+ - Deck components can share state across slides and windows: `import { useShared, useView } from 'mdeck/component'`. `useShared('count', 0)` works like `useState`, but every slide, the presenter's slide, the audience window, other windows in the browser and a paired iPad see the same value, and a window opened later gets it. `useView()` says which window a component is in. `mdeck/component` is the first part of mdeck that components may rely on; the authoring reference says what it promises and what stays mdeck's own.
34
+ - A drawing that uses the palette (an SVG with `var(--…)`) builds up in the order its parts are numbered: `data-step="1"`, `data-step="2"` … reveal one press at a time, parts with the same number together, whatever their order in the file, which is also the order they are drawn in. Bare `data-step` parts still appear in document order. With hotspots on, `data-hotspot` on a part makes it a hotspot once it is shown.
35
+ - Fixed: a drawing on two slides lost its arrowheads, gradients and `<use>` copies on the second, because `url(#…)` found the copy on the hidden first slide. Each copy in the page now gets ids of its own.
36
+ - `mdeck check` looks at the deck's SVG drawings: palette names without a fallback, fixed colours that stay the same in every palette and in dark mode, style rules that reach the rest of the page, numbered and bare steps in one drawing, and `data-step` or `data-hotspot` in a drawing that uses no palette colour and so is shown as a picture.
37
+ - The slide-writing skill draws diagrams as SVG in the palette's colours, builds them up with numbered steps and checks them in light and dark.
38
+ - A deck shared in part, with `--slide` or `--no-polls`, keeps the time its slides were planned to take as its `time:`, so the presenter view's countdown fits the part. The note that slides with polls were left out now appears only when one of the chosen slides had a poll.
39
+ - Fixed: a YouTube video in `<videoplayer>` showed "This video is unavailable" on a device that opened the deck through a server, such as a paired iPad. Such pages send no referrer, which YouTube requires of embedded players; the player now sends the deck's origin (never its path).
40
+ - Fixed: in a deck with polls, every slide change in the presenter view read the whole deck several times over to find out whether it has any. On an iPad presenting a large deck, slides changed noticeably slower than in the audience window. The answer is now kept until the deck changes.
41
+ - `--slide 3,5-7` for `mdeck send`, `mdeck build` and `mdeck pdf` keeps only these slides, for example the part of a deck shown in one lecture, with their drawings. The numbers count the slides as written, like `mdeck snapshot --slide` and `mdeck check --render`. A `<style>` written on a slide that is left out moves to the first slide kept, since it styles the whole deck; the same now holds for slides left out with `--no-polls`.
42
+ - Fixed: a stroke or laser trail drawn on a paired iPad could stop short in the audience window. Two batches of ink could be on their way at once and arrive in the other order, and a batch lost to the network was gone; the window then dropped that piece and everything after it. Batches now go one after another, a lost one is sent again, and a piece that arrives early waits for the one before it. While the network or the server is gone, the iPad tries again less and less often, up to every five seconds, and keeps only the laser's and the zoom's last position.
43
+ - Ink and the laser drawn on a paired iPad reach the audience window sooner: about 60 ms after the pen instead of 100 to 150 ms.
44
+ - The laser's trail stays on the screen as long as the pen is down, also in the audience window and on paired devices, so a circle or an underline can be shown while you talk about it. Lifted, it retracts as before.
45
+ - The presenter view's slide number is a field: type a number and press Enter (Go on an iPad) to jump to that slide, in the iPad's slide-only layout beside the arrows and in the speaker layout. The audience window and paired devices follow.
46
+
3
47
  ## 3.10.1 — 2026-10-11
4
48
 
5
49
  - Theme settings can be text: `type = "text"` for words a theme shows, such as Terminal's prompt. Authors write them as they should appear (`prompt: "~/demo $ "`), spaces included, and mdeck quotes them for the stylesheet; the editor shows a text box with the theme's own words. Before, such words could only be fixed in the theme.
package/README.md CHANGED
@@ -31,6 +31,18 @@ Polls, scales, word clouds, open questions and numbers to guess. People scan the
31
31
  </tr>
32
32
  <tr>
33
33
  <td width="50%" valign="top">
34
+ <a href="docs/site/images/features/hotspots.webp"><img src="docs/site/images/features/hotspots.webp" alt="The projector zoomed in on a table, and in front of it the presenter view showing the same slide with numbered keys on its code, table and formula"></a>
35
+ <p><b><a href="https://gh.tschieber.de/mdeck/presenting.html#zoom-in-on-part-of-a-slide">Zoom into a chart, a table or a line of code</a></b><br>
36
+ Turn on hotspots, and the presenter view puts a number on each picture, table, formula and code block. Press it, and the slide glides in until that part fills the projector; press it again to see the whole slide. The audience never sees the numbers.</p>
37
+ </td>
38
+ <td width="50%" valign="top">
39
+ <a href="docs/site/images/features/languages.webp"><img src="docs/site/images/features/languages.webp" alt="The same slide with a Python example in English, German, Hindi and Farsi, the Farsi one running right to left"></a>
40
+ <p><b><a href="https://gh.tschieber.de/mdeck/presenting.html#one-talk-in-several-languages">Give the talk in the room's language</a></b><br>
41
+ Keep <code>talk.en.md</code> beside <code>talk.de.md</code>, and press <b>L</b> to switch languages in the middle of the talk: slides, notes and every screen change at once, and you stay on the same slide. Farsi, Arabic and Hebrew run right to left.</p>
42
+ </td>
43
+ </tr>
44
+ <tr>
45
+ <td width="50%" valign="top">
34
46
  <a href="docs/site/images/features/citations.webp"><img src="docs/site/images/features/citations.webp" alt="A slide with author–year citations and the full references at its foot, over a slide that lists all references"></a>
35
47
  <p><b><a href="https://gh.tschieber.de/mdeck/more-content.html#cite-a-source">Cite your sources properly</a></b><br>
36
48
  Cite as in a paper, <code>[@knuth1984, p. 97]</code>, from the BibTeX, CSL-JSON or Hayagriva file you already keep. Each slide lists what it cites at its foot, in APA, Vancouver, Harvard or any CSL style.</p>
@@ -160,9 +172,9 @@ mdeck send talk.md # one file to email, with a PDF inside
160
172
  - **Layouts:** title, chapter, big statement, image and text, split, full-bleed image, and plain content slides, with points that appear one at a time.
161
173
  - **Looks:** six built-in themes and six colour palettes, each light or dark, changeable without touching the slides. Install more from the [theme repository](https://gh.tschieber.de/mdeck-themes/) with `mdeck themes install`, or make your own as small `extension.toml` folders beside the deck.
162
174
  - **One launch page:** `mdeck run` opens a page with a live preview, the presenter and audience views, the deck and reader views, the editor, the guides, one-click builds and PDF, the deck's check results, and for decks with a server its health and the presenter code.
163
- - **Presenting:** a presenter view with notes and timer, and an audience window that stays in sync. With `hotspots: auto`, the number keys zoom smoothly into a slide's pictures, code and tables, and the audience window zooms along.
175
+ - **Presenting:** a presenter view with notes and timer, and an audience window that stays in sync. **B** blacks out the audience's screen, **O** shows all slides to pick one, and a paired phone becomes a remote with your notes. With `hotspots: auto`, the number keys zoom smoothly into a slide's pictures, code and tables, and the audience window zooms along.
164
176
  - **Drawing on slides:** pen with pressure, highlighter and a laser pointer, with a mouse, a finger or an iPad pencil (`D`). Drawings are saved in `<deck>.drawings.json` beside the deck and appear in every view, build and PDF. An iPad can present on its own, or pair with the laptop through a QR code on the launch page while the laptop's audience window follows it.
165
- - **Audience questions:** `<poll room="lunch" options="A|B|C" />` shows live results and a QR code; people vote on their phones. `<scale>`, `<wordcloud>` and `<question>` ask for a rating, words or open answers, and `<qrcode join />` shows the join code once for all of them. Rooms run inside `mdeck run --network` or on a small server (`mdeck server`).
177
+ - **Audience questions:** `<poll room="lunch" options="A|B|C" />` shows live results and a QR code; people vote on their phones. `<scale>`, `<wordcloud>` and `<question>` ask for a rating, words or open answers, and `<qrcode join />` shows the join code once for all of them. With `reactions: true` people can also tap 👍 or 🐢 at any time, shown only to you. The answers save as CSV or JSON from the launch page. Rooms run inside `mdeck run --network` or on a small server (`mdeck server`).
166
178
  - **Sharing:** a reader view with an outline, a phone-friendly Read mode and a PDF download; speaker notes are stripped from shared builds, and interactive slides appear in their finished state.
167
179
  - **Citations:** cite with `[@key]` from BibTeX, CSL-JSON or Hayagriva files; each slide lists its references at its foot, `<bibliography />` lists them all, in any CSL style.
168
180
  - **Content:** pictures, video, tables, callouts, code with syntax highlighting and live execution, formulas, QR codes, and your own Preact components, kept with one deck or shared between decks.
@@ -188,9 +200,8 @@ complete folder.
188
200
 
189
201
  | Example | Theme | What it demonstrates |
190
202
  |---|---|---|
191
- | [Tour](examples/showcase/slides.md) | Glass | Start here: each slide shows the Markdown beside what it becomes, from headings to layouts, live code, notes, drawing, zooming into a part, a poll and sharing |
203
+ | [Tour](examples/showcase/slides.en.md) | Neue | Start here: each slide shows the Markdown beside what it becomes, from headings to layouts, live code, citations, notes, drawing, zooming into a part, timing the talk, a poll, a word cloud and reactions from the room, and sharing; in English, [German](examples/showcase/slides.de.md) and [Arabic](examples/showcase/slides.ar.md) |
192
204
  | [Python](examples/python/slides.en.md) | Academic | A real lesson: live code to try out, points revealed step by step, notes on every slide, a poll to check understanding; in English, [German](examples/python/slides.de.md), [Hindi](examples/python/slides.hi.md) and [Farsi](examples/python/slides.fa.md), switched in the presenter view |
193
- | [Poll](examples/poll/slides.md) | Neue | A join slide, then a poll, a scale, a word cloud and open questions; start it with `mdeck run slides.md --network` |
194
205
  | [Custom layouts](examples/custom-layouts/slides.md) | Neue | A deck-local comparison design and named regions |
195
206
 
196
207
  The docs home page embeds a short talk, and the screenshots above show Neue.
package/assets/base.css CHANGED
@@ -183,7 +183,10 @@ deck-stage[data-ink-hidden] .slide-ink { display: none; }
183
183
  /* ── Code blocks ─────────────────────────────────────────────────────────── */
184
184
  .code-block { white-space: pre-wrap; overflow-x: hidden; }
185
185
  /* Code and maths read from left to right, also on a right-to-left slide. */
186
- .slide[dir="rtl"] :is(pre, code, kbd, samp, .katex, .code-block-wrapper) { direction: ltr; unicode-bidi: isolate; }
186
+ .slide[dir="rtl"] :is(pre, code, kbd, samp, .katex, .code-block-wrapper, .themed-picture) { direction: ltr; unicode-bidi: isolate; }
187
+ /* A citation and a reference read in their own direction: Latin names stay in
188
+ order beside Arabic text, and a reference list in Latin script stays left aligned. */
189
+ .slide[dir="rtl"] .citation, .slide[dir="rtl"] .slide-citations .csl-entry { unicode-bidi: plaintext; }
187
190
  /* A bullet that points along the line points the other way. */
188
191
  .slide[dir="rtl"] .slide-body ul > li::before { scale: -1 1; }
189
192
 
@@ -238,6 +241,8 @@ deck-stage[data-ink-hidden] .slide-ink { display: none; }
238
241
  [data-step][data-step-visible] {
239
242
  opacity: 1;
240
243
  }
244
+ /* The overview (O) shows each slide whole, to find it by. */
245
+ deck-stage[data-overview] [data-step] { opacity: 1; }
241
246
 
242
247
  /* ── Print ───────────────────────────────────────────────────────────────── */
243
248
  @media print {
@@ -67,7 +67,9 @@ Each `---` line starts a new slide. Frontmatter is only needed when you want a s
67
67
  | `csl` | `apa` | Citation style: `apa`, `vancouver`, `harvard1`, or a `.csl` file |
68
68
  | `nocite` | — | References to list without citing them; `['*']` lists the whole file |
69
69
  | `show.citations` | `true` | `false` leaves out each slide's own references above the footer |
70
- | `hotspots` | `off` | Number keys zoom in on parts of a slide while presenting: `auto` (pictures, code, tables, formulas, videos, callouts, columns, polls and `data-hotspot` elements), `marked` (only `data-hotspot` elements) or `off` (1–9 go to slides) |
70
+ | `time` | — | How long the talk takes, such as `20m`: slides without their own `time` share what is left (see [Time your talk](../site/content/presenting.md#time-your-talk)) |
71
+ | `hotspots` | `off` | Number keys zoom in on parts of a slide while presenting: `auto` (pictures, code, tables, formulas, videos, callouts, columns, polls and `data-hotspot` elements), `marked` (only `data-hotspot` elements) or `off` (the number keys do nothing) |
72
+ | `reactions` | — | Reaction buttons on the phones' answer page; a tap floats up on the presenter's screen only, and is not kept: `true` (👍 👏 ❤️ 😮 🤔 🐢) or a list of 1 to 8 emoji or words of up to 16 characters |
71
73
 
72
74
  ### Theme params
73
75
 
@@ -112,6 +114,34 @@ then the reader shows them only when `reader.notes` is `true`, so a file can
112
114
  carry notes for the presenter view without showing them to readers. The same
113
115
  view is reachable in any build through `?view=reader`.
114
116
 
117
+ ## Including other decks
118
+
119
+ A slide that is nothing but an `:::include` line, with no settings, stands for the slides of another deck file:
120
+
121
+ ```markdown
122
+ ---
123
+ :::include ./lectures/02-graphs.md
124
+ ---
125
+ :::include ./lectures/02-graphs.md slides=3-7
126
+ ---
127
+ :::include "./lectures/week 3.md"
128
+ ```
129
+
130
+ - The included file is a complete deck and can be presented alone; a file of slides without deck settings can be included too. When it is included, its slides come along with what they need from its settings, and the look stays the including deck's:
131
+ - `hotspots` and `time` become each included slide's own, unless it has one. A slide without a time gets its share of the included deck's `time`, shared out as that deck does alone (its slides' own times first, the rest in equal parts); `slides=` keeps each chosen slide's share.
132
+ - `bibliography` files and `nocite` keys are added to the including deck's; `csl` too, when the including deck sets none. Its `<bibliography />` lists the works it cites itself (and its `nocite`), not every work of the including deck.
133
+ - `components` folders, and a `components/` folder beside the included file, are added to the including deck's.
134
+ - Callout names of its own under `callouts` are added, unless the including deck names them; titles it gives built-in callouts are not.
135
+ - `theme`, `palette`, `appearance`, `params`, `width`, `height`, `lang`, `labels`, `show`, `meta`, `reader`, `server` and `session` are ignored, and a problem with them is not reported for the including deck.
136
+ - A block at the top of an included file with only `time:` or `hotspots:` (keys both a deck and a slide have) is read as the file's settings, for all its slides; `mdeck check` says so. For the first slide alone, write them in a `:::meta` block.
137
+ - `slides=` keeps the slides with these numbers (`3`, `3,5`, `2-4`), counted as the included file shows them, like `--slide`.
138
+ - Local paths (Markdown pictures, `<img>`, `<video>`, `<videoplayer>` and `<audio>` sources, `image:` and `logo:`) are read from the included file's folder. Paths from the root (`/…`) stay as written.
139
+ - Includes may nest. A file that includes itself, directly or through others, is an error, as is a missing file or a slide number beyond the file.
140
+ - In a deck whose file name gives a language (`course.de.md`), `./part.md` is read as `./part.de.md` when that file exists.
141
+ - Ids: slides of the including deck keep the ids they have in it; included slides get the included file's name in front of theirs, without leading digits (`02-graphs.md` → `graphs-slide-3`, `graphs-dijkstra`), with `-2`, `-3` … when the same name comes up again. Drawings made while presenting are saved under these ids, in the including deck's drawings file.
142
+ - Saved rehearsal times go into the file the slide is written in. The editor (`mdeck edit`) shows an include as one card; edit included slides in their own file.
143
+ - Palettes, layouts and themes are found beside the including deck.
144
+
115
145
  ## Available themes
116
146
 
117
147
  | Key | Description |
@@ -172,6 +202,7 @@ description: A short description shown under the title.
172
202
  | `section` | Section label shown in the slide header (auto-propagated — see below) |
173
203
  | `title` | Name in the outline and reader navigation, for slides without a heading (not shown on the slide) |
174
204
  | `hotspots` | This slide's own hotspots: `auto`, `marked`, `off` or `false` (see the deck field) |
205
+ | `time` | How long to spend on the slide: `90s`, `2m`, `1m30s` or `1.5m`. The presenter view counts it down; `mdeck rehearse` measures and saves it |
175
206
 
176
207
  ### Section labels
177
208
 
@@ -423,7 +454,7 @@ As @smith2020 showed, it works [see @smith2020, p. 12; @doe2019].
423
454
  | `@smith2020 [chap. 3]` | Smith et al. (2020, Chapter 3) | Smith et al. (1) |
424
455
 
425
456
  - **On the slide** each citation shows in the style's short form, and the full reference of every work the slide cites stands in small type above the footer, after any footnotes. `show.citations: false` leaves those out.
426
- - **`<bibliography />`** lists every cited work, plus those named in `nocite`, in the style's order. A list too long for one slide goes on several: `<bibliography part="1/2" />` on one and `<bibliography part="2/2" />` on the next split it in halves.
457
+ - **`<bibliography />`** lists every cited work, plus those named in `nocite`, in the style's order. A list too long for one slide goes on several: `<bibliography part="1/2" />` on one and `<bibliography part="2/2" />` on the next split it in halves. `<bibliography keys="smith2020 doe2019" />` lists only these works. In a deck that includes others, an included deck's `<bibliography />` lists the works that deck cites, as it does when shown alone, and the including deck's own lists every work.
427
458
  - **Locators** after a comma: `p.`/`pp.`, `chap.`, `sec.`, `fig.`, `vol.`, `para.`, `no.`, `l.`, `eq.` and the German `S.`, `Kap.`, `Abb.`, `Bd.`, `Nr.`; a bare number is a page.
428
459
  - **`@key` without brackets** is a citation only when the key is in the reference file, so e-mail addresses and `@handles` stay text. Citations in code, in links' addresses and in `:::notes` blocks work as in slide text, except that notes show no reference footer.
429
460
  - **A key that is not in the file** shows as `@key?`, marked, and `mdeck check` and `mdeck build` warn about it.
@@ -543,7 +574,7 @@ A title written after the type on the `:::` line still wins over both.
543
574
 
544
575
  ## Language
545
576
 
546
- `lang` is the language of the whole deck. The page is marked with it, so screen readers pronounce the slides correctly and browsers hyphenate them. It also picks the words mdeck itself shows the audience: the reader view's buttons, the deck's control bar, polls on the slide and on phones, and callout titles. German (`de`) and English (`en`) are built in; for any other language the words stay English. A regional code such as `de-CH` uses the German words.
577
+ `lang` is the language of the whole deck. The page is marked with it, so screen readers pronounce the slides correctly and browsers hyphenate them. It also picks the words mdeck itself shows the audience: the reader view's buttons, the deck's control bar, polls on the slide and on phones, and callout titles. English (`en`), German (`de`) and Arabic (`ar`) are built in; for any other language the words stay English. A regional code such as `de-CH` uses the German words.
547
578
 
548
579
  The presenter view, the launch page and the editor are tools for the author and always stay English.
549
580
 
@@ -709,9 +740,33 @@ palette's custom properties (`--bg`, `--surface`, `--ink`, `--ink-soft`,
709
740
  `--muted`, `--rule`, `--accent`, `--accent-2`, `--accent-3`, `--on-accent`) and follows the
710
741
  theme, palette and appearance. Give each a fallback (`var(--accent, #1f3fd1)`)
711
742
  for places that show the file on its own, set `fit: contain` to keep the whole
712
- drawing, prefix class names in its `<style>` because inline styles apply to the
713
- page, and avoid `id`s, since a slide can be shown more than once. Such SVGs stay
714
- files in single-file builds and travel inside the deck's code instead.
743
+ drawing, and start every rule in its `<style>` with a class of the drawing's
744
+ own (`.flow-box`), because inline styles apply to the page. Each copy in the
745
+ page gets ids of its own, and `url(#…)` and `href="#…"` inside it follow them,
746
+ so markers, gradients and `<use>` work on every slide that shows the drawing;
747
+ `#id` selectors in its `<style>` do not. Such SVGs stay files in single-file
748
+ builds and travel inside the deck's code instead.
749
+
750
+ Being part of the slide, such a drawing can build up: `data-step` on its parts
751
+ reveals them one press at a time. Numbered parts (`data-step="1"`,
752
+ `data-step="2"` …) appear in the order of their numbers, and parts with the
753
+ same number together, whatever their order in the file, which is also the order
754
+ they are drawn in; the drawing's steps come where its first step is in the
755
+ slide. Bare `data-step` parts appear in document order. With hotspots on,
756
+ `data-hotspot` on a part makes it a hotspot once it is shown.
757
+
758
+ ```svg
759
+ <g data-step="1" data-hotspot>…input…</g>
760
+ <g data-step="1">…output…</g>
761
+ <g data-step="2">…the arrow, drawn under both…</g>
762
+ ```
763
+
764
+ `mdeck check` warns about a palette name without a fallback (`svg-fallback`),
765
+ fixed colours that do not follow the palette or dark mode (`svg-fixed-colour`),
766
+ style rules that reach beyond the drawing (`svg-style`), numbered and bare steps
767
+ in one drawing (`svg-steps`), and `data-step` or `data-hotspot` in an SVG that
768
+ uses no palette colour, which is shown as a picture and so cannot build up
769
+ (`svg-not-inline`).
715
770
 
716
771
  A normal build copies referenced local images, video, and audio next to the HTML
717
772
  while preserving their deck-relative paths. This is the recommended distribution
@@ -781,7 +836,7 @@ For `play="auto"` the video pauses and resets to the beginning when you navigate
781
836
  | `room` | `poll` | Name of the room that collects the answers; unique per poll in a deck. Letters, digits, `.`, `-`, `_` |
782
837
  | `options` | — | Answers separated by `\|`. Markdown and `$…$` maths, as on a slide (see below). Or a list inside the tag |
783
838
  | `question` | — | Question text, Markdown and maths like `options`; phones fall back to the slide heading |
784
- | `qr` | `true` | `false` leaves out the QR code (shown earlier with `<qrcode join />`) |
839
+ | `qr` | `false` | Puts the join code beside the question; **J** in the presenter view shows it over any slide |
785
840
  | `answer` | — | The right answer (several separated by `\|`): a button with a tick outlines its label, bar and count in green, also in the audience window and on paired devices, and each phone says whether its vote was right. `--poll-correct` sets the colour |
786
841
  | `multiple` | — | Each phone may pick several options; the slide and the phones say so. A vote is then the list of options picked, and is right when it is exactly the `answer` options |
787
842
  | `buttons` | — | `letters` puts A, B, C … before the options, and the phones show only those; `numbers` does the same with 1, 2, 3 …. For options better read on the slide, such as pictures (`options="![](a.svg)\|![](b.svg)"`) |
@@ -793,7 +848,7 @@ Four more activities take the same `room`, `question` and `qr`:
793
848
  |---|---|---|---|
794
849
  | `<scale>` | `min` (1), `max` (5), `low`, `high` | One button per number, `low`/`high` as labels | Count per number and the average; latest answer per device |
795
850
  | `<numeric>` | `answer`, `tolerance` (0), `limit` (6), `placeholder`, `results` | A number field: `0.5`, `0,5`, `1/2`, `1e-3`; latest answer per device | The most frequent answers as bars, the rest as Other; with `answer`, the tick marks the right ones, counts them and tells each phone |
796
- | `<wordcloud>` | `placeholder`, `limit` (60), `height` (520) | Text field, up to 40 characters, repeatable | A packed word cloud (d3-cloud): size by frequency, some words upright, case-insensitive |
851
+ | `<wordcloud>` | `placeholder`, `limit` (60), `height` (520) | Text field, up to 40 characters; a phone's latest word counts | A packed word cloud (d3-cloud): size by frequency, some words upright, case-insensitive |
797
852
  | `<question>` | `placeholder`, `limit` (8) | Text field, up to 200 characters, repeatable | The newest answers as cards |
798
853
 
799
854
  `<qrcode follow />` shows the link for following the slides on phones and laptops (`?view=follow`), with `mdeck run --network` or a hosted deck with a `server` setting; the phones' answer page links to it as well. `<qrcode join />` shows the deck's join code large with its link (`size`, default 420), for a slide that invites everyone once; activities after it can use `qr="false"`. QR codes (`<qrcode>`, activities) are SVG in the slide's `--ink` on a transparent background; `--qr-ink` and `--qr-bg` override the colours.
@@ -818,10 +873,12 @@ The slide shows live bars, the number of answers, a QR code and a short link. Ph
818
873
 
819
874
  Every activity has a lock button that closes it: answers after that do not count, and the phones say it is closed until it opens again. Polls and `<numeric>` also have the eye that hides or shows the results. Below the results, polls, scales and `<numeric>` count “12 of 31 answered” while phones are connected (people following the slides count as phones). The lock, the eye and the tick reach every screen of the talk, also after a reload: they are kept in the activity room's state on the server, which only the presenter may set, and phones read it there. Reset clears the answers and opens the activity again.
820
875
 
821
- While `mdeck run` runs, the answers are kept beside the deck in `<slides>.results.json`: per activity room, each answer with its time, the phones numbered per room (their ids are not kept), and, once an activity was closed, only the answers that counted. Reset takes a room out of the file; a new, empty server leaves the file alone. Builds, `mdeck send` and `mdeck pdf` show the kept answers where no room server answers (`--no-results` leaves them out), and `mdeck results [slides.md] [-o file.csv]` prints them as CSV: `room,phone,at,answer`, several picks joined by `|`.
876
+ While `mdeck run` runs, the answers are kept beside the deck in `<slides>.results.json`: per activity room, each answer with its time, the phones numbered per room (their ids are not kept), and, once an activity was closed, only the answers that counted. Reset takes a room out of the file; a new, empty server leaves the file alone. Builds, `mdeck send` and `mdeck pdf` show the kept answers where no room server answers (`--no-results` leaves them out), and `mdeck results [slides.md] [-o file.csv]` prints them as CSV: `slide,room,kind,question,phone,at,answer`, several picks joined by `|` (`kind` is poll, scale, number, words or question; a room the deck no longer asks has no slide). `--summary` prints `slide,room,kind,question,answer,count,share`: one row per option, scale step, number or word, counted as the slide counts them (each phone's latest answer for polls, scales and numbers; every answer for words and questions), and `average` and `median` rows for scales and numbers. `--json` (or `-o file.json`) writes `{ version, title, exportedAt, questions: [{ room, slide, kind, question, closed, savedAt, summary, answers }] }`. The launch page offers the same three files.
822
877
 
823
878
  `--no-polls` leaves slides with an activity or a join code (`<qrcode join />`) out of `mdeck send`, `mdeck build --reader` and `mdeck pdf`; without it they show as a record of the talk. Saved drawings follow the remaining slides.
824
879
 
880
+ `--slide 3,5-7` keeps only these slides in `mdeck send`, `mdeck build` and `mdeck pdf`, numbered by their place in the deck as written. Drawings follow their slides, and `<style>` elements on the slides left out move to the first slide kept, since they style the whole deck.
881
+
825
882
  Rooms run inside `mdeck run` (add `--network` so phones can reach it) or on a server started with `mdeck server`, set in the deck:
826
883
 
827
884
  ```yaml
@@ -909,6 +966,51 @@ stays out of every other deck's bundle. Install such dependencies in a
909
966
  > hooks from `preact/hooks`. The build resolves those imports back to the
910
967
  > framework's own Preact, so the deck folder needs no Preact install.
911
968
 
969
+ ### Shared state across slides and windows
970
+
971
+ A component can keep a value that every slide and every window of the talk
972
+ share: the presenter's slide, the audience window, other deck windows in the
973
+ same browser, and a paired iPad. Import it from `mdeck/component`:
974
+
975
+ ```jsx
976
+ import { h } from 'preact'
977
+ import { useShared, useView } from 'mdeck/component'
978
+
979
+ export default function Counter() {
980
+ const [count, setCount] = useShared('count', 0)
981
+ return <button onClick={() => setCount(n => n + 1)}>{count}</button>
982
+ }
983
+ ```
984
+
985
+ - `useShared(name, initial)` returns the value and a function to set it, like
986
+ `useState`. `initial` stands in until a window sets one. Values must survive
987
+ JSON (numbers, text, lists, plain objects). The latest change wins.
988
+ - A window opened later, or reloaded, gets the current values from the others.
989
+ Nothing is saved: when every window of the talk is closed, the values are gone.
990
+ - `useView()` says which window the component is in: `presenter` (the
991
+ presenter view's slide), `audience`, `deck`, `follow` (a phone following the
992
+ talk), `preview` (the next-slide preview and the editor) or `reader`.
993
+ Previews, followers and the reader see shared values but do not change them.
994
+ - Choose names that belong to your component, such as `countdown` or
995
+ `quiz:round`: every component in the deck shares one set of names.
996
+
997
+ A button the presenter uses during the talk, such as one that starts or stops
998
+ something, can be offered in the presenter view's toolbar and on the phone
999
+ clicker: give it `data-presenter-control`, an `aria-label` (or a value for
1000
+ `data-presenter-control`) that says what it does, `aria-pressed` while it is
1001
+ on, and `data-presenter-icon` with one of mdeck's icon names. A press there
1002
+ clicks the button on the slide.
1003
+
1004
+ ```jsx
1005
+ <button data-presenter-control data-presenter-icon="play" aria-label="Start the countdown"
1006
+ aria-pressed={running} onClick={toggle}>…</button>
1007
+ ```
1008
+
1009
+ `mdeck/component` and these attributes are the part of mdeck that components
1010
+ may rely on; they are kept stable across versions. A component renders inside its slide. Anything
1011
+ else it reaches, such as the page outside its slide, the `<deck-stage>`, mdeck's
1012
+ events or the presenter view, is not part of it and may change without notice.
1013
+
912
1014
  ---
913
1015
 
914
1016
  ## Inline HTML
@@ -68,6 +68,8 @@ h1 { font-size: clamp(32px, 3vw, 46px); margin: 0 0 24px; max-width: 23ch; }
68
68
  .welcome h1 { font-size: clamp(40px, 4.5vw, 63px); line-height: 1.08; max-width: 14ch; letter-spacing: -.055em; }
69
69
  .welcome article > p:first-of-type { font-size: 20px; line-height: 1.55; color: var(--secondary); max-width: 53ch; }
70
70
  .welcome article > p:nth-of-type(3) > a { display: inline-block; background: var(--blue); color: white; text-decoration: none; padding: 10px 19px; border-radius: 5px; font-size: 15px; font-weight: 600; }
71
+ .welcome article > p:nth-of-type(3) { display: flex; flex-wrap: wrap; gap: 8px; }
72
+ .welcome article > p:nth-of-type(3) > a + a { background: none; color: var(--blue); box-shadow: inset 0 0 0 1.5px var(--blue); }
71
73
  .welcome article { max-width: 820px; }
72
74
  .welcome article > :not(.features) { max-width: 76ch; }
73
75
  .features { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px 32px; margin: 24px 0 32px; }
@@ -128,7 +128,7 @@ Open the launch page and choose **Presenter view**:
128
128
  mdeck run my-talk.md
129
129
  ```
130
130
 
131
- Its theme, palette and light or dark controls, under the notes, let you try other looks (fold them away with the arrow beside them). These changes are a preview: they do not save back to your text file. Once you find a look you like, put its settings in the file and save.
131
+ Its settings (the slider button at the top) let you try other themes, palettes and light or dark. These changes are a preview: they do not save back to your text file. Once you find a look you like, put its settings in the file and save.
132
132
 
133
133
  ## More themes from other people
134
134
 
@@ -34,7 +34,7 @@ Every poll in a presentation shows the same code, so people scan once. Their pho
34
34
  | `multiple` | Each phone may pick several options. The slide and the phones say “Several answers possible”. Without it, one option per phone. |
35
35
  | `buttons` | `letters` puts A, B, C … before the options on the slide, and the phones show only those letters; `numbers` does the same with 1, 2, 3 … For options that are pictures or long formulas, better read on the big screen. |
36
36
  | `results` | `hidden` starts with the bars hidden, e.g. to let people vote before they see what others chose. |
37
- | `qr` | `false` leaves out the QR code, when an earlier slide showed it with `<qrcode join />`. |
37
+ | `qr` | Puts the deck's join code beside the question. Usually not needed: **J** shows it over any slide (see below). |
38
38
 
39
39
  The question and the options may contain formatting and formulas, written as on a slide, so a maths lecture can ask:
40
40
 
@@ -91,14 +91,16 @@ Besides a poll, four more kinds work the same way: one line on a slide, answered
91
91
  |---|---|---|
92
92
  | `<scale>` | The numbers from `min` to `max` (1 to 5 unless set, at most 11 steps), with `low` and `high` as labels at the ends | How many chose each number, and the average. Each phone's latest answer counts |
93
93
  | `<numeric>` | A field for a number: `0.5`, `0,5`, `1/2` or `1e-3` | The most frequent answers as bars, six unless `limit` says otherwise, and the rest as Other. With `answer`, the tick marks the right ones and counts them, and each phone hears whether it was right; `tolerance` (0 unless set) says how far off still counts. Each phone's latest answer counts |
94
- | `<wordcloud>` | A short text field | A cloud of every answer, packed around the middle, larger the more often it came in and some upright. Capitals and extra spaces do not matter. People may send several. `height` sets its height (520). Colours come from the palette; `--cloud-1` to `--cloud-6` override them |
94
+ | `<wordcloud>` | A short text field | A cloud of every answer, packed around the middle, larger the more often it came in and some upright. Capitals and extra spaces do not matter. Each phone counts with one word: a new one replaces its earlier word. `height` sets its height (520). Colours come from the palette; `--cloud-1` to `--cloud-6` override them |
95
95
  | `<question>` | A text field | The newest answers as cards, eight unless `limit` says otherwise. People may send several |
96
96
 
97
97
  All of them take `room`, `question` and `qr` like a poll, and `placeholder` for the text fields. Their `question`, and the scale's `low` and `high`, may contain formatting and formulas like a poll's options. All of them have the lock that closes them; `<numeric>` also has the eye and the tick, and takes `results="hidden"`.
98
98
 
99
- ## Show the code once
99
+ ## Let phones join
100
100
 
101
- Each question shows the QR code unless you say otherwise. To invite everybody once, at the start, put the code on a slide of its own and leave it out of the questions:
101
+ Questions show no QR code of their own. When people should join, press **J** in the presenter view (or the QR-code button): the deck's join code appears large over the slide on the projector and every other screen, with the link below it. Phones that scanned it follow along to every question. **J** again, or the next step, shows the slide again; press it once more for people who arrive late.
102
+
103
+ To keep the code on a slide of its own, or beside one question, write it there:
102
104
 
103
105
  ```markdown
104
106
  ---
@@ -109,10 +111,12 @@ Each question shows the QR code unless you say otherwise. To invite everybody on
109
111
  ---
110
112
  # How do you make slides today?
111
113
 
112
- <poll room="tools" options="PowerPoint|Keynote|Markdown" qr="false" />
114
+ <poll room="tools" options="PowerPoint|Keynote|Markdown" />
113
115
  ```
114
116
 
115
- `<qrcode join />` shows the presentation's join code large, with the link below it. Phones that scanned it follow along to every question. With `qr="false"`, a question leaves out its own code. Leave the join slide up for a while, or come back to it, for people who arrive late. `size` sets the size of the code on the join slide.
117
+ `<qrcode join />` shows the join code large on that slide (`size` sets its size); `qr` on a question puts the code beside it.
118
+
119
+ The presenter view's connection icons show the join link to copy, and whether phones can reach the poll server.
116
120
 
117
121
  The code is drawn in the slide's colours, so it fits the theme; phone cameras also read light codes on dark slides.
118
122
 
@@ -122,6 +126,20 @@ The code is drawn in the slide's colours, so it fits the theme; phone cameras al
122
126
 
123
127
  It needs their devices to reach your slides: present with `mdeck run --network` when everyone is on the same Wi-Fi (it prints the **Follow** address), or host the built deck with a `server` setting for people anywhere.
124
128
 
129
+ ### Reactions
130
+
131
+ Let people react while you talk, with or without a question on screen:
132
+
133
+ ```markdown
134
+ ---
135
+ reactions: true
136
+ ---
137
+ ```
138
+
139
+ The phones' answer page then has a row of buttons, 👍 👏 ❤️ 😮 🤔 🐢, below the question or while they wait for the next one. A tap floats up in the corner of your presenter view for a moment, and a small tally keeps what came in the last minute, so a few 🐢 ("slower, please") still show after they faded. The audience window and the projector never show them. Give your own, up to eight emoji or short words: `reactions: [👍, 🤔, 🐢, louder]`. Each phone can react about once a second; reactions are not kept anywhere.
140
+
141
+ People reach the answer page through the join code: press **J** in the presenter view to show it, also in a deck with reactions and no questions.
142
+
125
143
  Hover over the results to see **Reset**, which clears the answers, for example before the real session. Only the presenter can reset.
126
144
 
127
145
  ## How phones and slides meet
@@ -206,7 +224,7 @@ server: https://rooms.example.org
206
224
  ---
207
225
  ```
208
226
 
209
- To keep the address out of the deck, leave the setting out and set `MDECK_SERVER=https://rooms.example.org` in your shell instead; `mdeck run --server` then finds it. A built or sent presentation reads the address from the deck only, because it has to carry it to wherever it is opened.
227
+ To keep the address out of the deck, leave the setting out and set `MDECK_SERVER=https://rooms.example.org` in your shell instead. With `MDECK_SERVER_KEY` set as well, `mdeck run` then uses the server by itself, without `--server`; when the server does not answer, it says so and presents from your computer, and `--no-server` leaves it out on purpose. A built or sent presentation reads the address from the deck only, because it has to carry it to wherever it is opened.
210
228
 
211
229
  `MDECK_SERVER_KEY` is the server’s master key. `mdeck run` keeps it on your computer and lets your local browser, or an iPad with a revocable pairing token, move the phones along and reset polls for this deck. Pairing QR codes never include the master key. Start `mdeck run` with the same key (`MDECK_SERVER_KEY=choose-a-secret mdeck run my-talk.md`), and the launch page checks the server, shows the join link and opens the presenter view. Paired devices remember only their token, scoped to this presentation; it never appears in the address bar or in the slide file. A hosted presenter can still unlock the server by opening the presenter view once with `?serverkey=…` in its address. That browser remembers the master key. Without permission to control the server, phones wait. The presenter view says whether the phones follow it, and if not, why.
212
230
 
@@ -218,7 +236,17 @@ Two presentations with the same title share a session code. Give one of them `se
218
236
 
219
237
  Answers are anonymous. Each phone gets a random number so it can change its vote; nothing else identifies it. The server keeps answers in memory only. It forgets a room after twelve hours without visitors and everything when it restarts. Each phone can send a limited number of answers in a short time.
220
238
 
221
- While you present with `mdeck run`, the answers are also kept beside the presentation, in `my-talk.results.json`. It holds each answer with its time, and the phones numbered 1, 2, 3 … per question instead of their random numbers. Once a question was closed, only the answers that counted. **Reset** takes a question's answers out of the file; a new server that starts empty leaves the file as it is. `mdeck results my-talk.md` prints the answers as CSV (question, phone, time, answer), to open in a spreadsheet; `-o answers.csv` saves them to a file. A deck hosted with its own `server` keeps nothing beside it.
239
+ While you present with `mdeck run`, the answers are also kept beside the presentation, in `my-talk.results.json`. It holds each answer with its time, and the phones numbered 1, 2, 3 … per question instead of their random numbers. Once a question was closed, only the answers that counted. **Reset** takes a question's answers out of the file; a new server that starts empty leaves the file as it is. A deck hosted with its own `server` keeps nothing beside it.
240
+
241
+ ### Save the answers
242
+
243
+ Under **Answers from the talk**, the launch page lists each question with how many phones answered and how it came out, and saves the answers as a file:
244
+
245
+ - **Answers (CSV)**: every answer on its own row, with the slide, the question, the phone's number and the time, to open in a spreadsheet.
246
+ - **Summary (CSV)**: one row per option, number on a scale, number typed or word, with how many chose it and their share; for scales and numbers also the average and the median. It counts as the slide does: each phone's last vote.
247
+ - **Everything (JSON)**: all of it, for other programs.
248
+
249
+ On the command line, `mdeck results my-talk.md` prints the answers as CSV, `--summary` the summary and `--json` everything; `-o answers.csv` (or `.json`) saves them to a file.
222
250
 
223
251
  ## In a PDF or a shared file
224
252
 
@@ -11,6 +11,7 @@ For how the commands, the views and the servers fit together, see [Views, comman
11
11
  | `mdeck skill --install claude` | Teach your AI assistant to write mdeck slides ([details](claude-skill.html)) |
12
12
  | `mdeck new` | Make a presentation with guided questions |
13
13
  | `mdeck run my-talk.md` | Open the launch page: present, edit, check and send from one place; slides reload when you save |
14
+ | `mdeck rehearse my-talk.md` | Rehearse the talk: each slide is timed, and the times can be saved into the deck ([details](presenting.html#rehearse)) |
14
15
  | `mdeck edit my-talk.md` | Edit slides, colors and themes in the browser; saves to the file |
15
16
  | `mdeck themes search`, `install <theme>`, `remove`, `update`, `list` | Themes: install more (each with its palette), remove the ones you do not use; see [Install, remove or share a theme](theme-repository.html) |
16
17
  | `mdeck palettes search`, `install <palette>`, … | The same for palettes |
@@ -32,7 +33,7 @@ For how the commands, the views and the servers fit together, see [Views, comman
32
33
  `mdeck run my-talk.md` opens a page on your own computer with everything for this talk. It is what the preview's plain address, such as `http://localhost:5173/`, shows; the slides themselves are at `?view=deck`.
33
34
 
34
35
  - **Preview:** a small live copy of the deck to flip through; click it to open the audience window at that slide.
35
- - **Present:** the presenter view, audience window and reader view, each in a new tab. The presenter view has notes, drawing controls, a timer and next-slide preview; switch to its slide-only layout for a single screen. The audience window shows slides without notes. Fullscreen is a control inside either view, not a separate view.
36
+ - **Present:** the presenter view, audience window and reader view, each in a new tab. The presenter view has notes, drawing controls, a timer and next-slide preview; **Rehearse** opens it timing each slide; switch to its slide-only layout for a single screen. The audience window shows slides without notes. Fullscreen is a control inside either view, not a separate view.
36
37
  - **Write and learn:** the visual editor, the theme editor (themes and palettes on a sample deck, see [Install, remove or share a theme](theme-repository.html)) and these guides. Each starts the first time you click it.
37
38
  - **Send:** buttons that make the `dist` folder, one file to send, or a PDF, next to your slide file, and show them in your file manager.
38
39
  - **Polls:** for a deck with polls: the server (built in, or the `server` setting and whether it answers), the join link and session code for phones, and for a server of your own the key that lets your browser move the phones along and reset polls (see below).
@@ -45,7 +46,8 @@ Two options make the slides reachable from other devices:
45
46
  | Option | What it does |
46
47
  |---|---|
47
48
  | `--network` | Phones and tablets on the same network can open the slides. |
48
- | `--server` | An iPad on any network can present through your own server. It takes the server's address, or finds it in the deck's `server` setting or in the `MDECK_SERVER` variable, in that order. The key goes in `MDECK_SERVER_KEY`. |
49
+ | `--server` | An iPad on any network can present through your own server. It takes the server's address, or finds it in the deck's `server` setting or in the `MDECK_SERVER` variable, in that order. The key goes in `MDECK_SERVER_KEY`. With both `MDECK_SERVER` and `MDECK_SERVER_KEY` set in your shell, `mdeck run` uses the server without `--server` whenever it answers, and presents from this computer when it does not. |
50
+ | `--no-server` | Present from this computer only, even with `MDECK_SERVER` set. |
49
51
 
50
52
  See [Draw on your slides](drawing.html#present-from-an-ipad) for both. The launch page itself and its buttons only work on your own computer. `--port 4000` chooses the port and `--no-open` starts without opening a browser.
51
53
 
@@ -94,11 +96,12 @@ The design page shows themes and palettes on a sample deck with every kind of sl
94
96
  | `mdeck send my-talk.md` | One file for readers: the reader view, speaker notes removed, a PDF inside |
95
97
  | `mdeck send my-talk.md --notes` | The same, keeping the speaker notes |
96
98
  | `mdeck send my-talk.md --no-polls` | The same, leaving out the slides with polls and their join codes |
99
+ | `mdeck send my-talk.md --slide 12-30` | The same with only slides 12 to 30 and their drawings; also for `build` and `pdf` |
97
100
  | `mdeck send my-talk.md --no-pdf` | The same, without rendering the PDF |
98
101
  | `mdeck pdf my-talk.md -o talk.pdf` | Render the slides to a PDF file (`--no-polls` leaves out the slides with polls) |
99
102
  | `--no-drawings` | Leave out the drawings from `my-talk.drawings.json`, for `build`, `send` and `pdf` |
100
103
  | `--no-results` | Leave out the answers kept in `my-talk.results.json`, for `build`, `send` and `pdf`; the polls then show their questions only |
101
- | `mdeck results my-talk.md` | The answers kept during the talk, as CSV; `-o answers.csv` saves them to a file |
104
+ | `mdeck results my-talk.md` | The answers kept during the talk, as CSV with the slide and the question; `--summary` one row per option or word with how many chose it, `--json` everything; `-o answers.csv` (or `.json`) saves them to a file |
102
105
 
103
106
  See [Send, host or print your slides](sharing.html) for help choosing between them. Unknown options, missing option values and extra filenames stop the command before it changes any output. `--output=path` and `-o path` are both accepted. `mdeck preview --no-open --port 4200` previews without opening a browser and chooses a port.
104
107
 
@@ -11,7 +11,7 @@ Press **D** in standalone slides or in the presenter view, or use the pen button
11
11
  | Pen | Thin to thick with the pencil's pressure. Kept. |
12
12
  | Highlighter | A wide, see-through stroke in its own colours, always below the pen's strokes. Kept. |
13
13
  | Select and move | Draw a loop around strokes, or tap one, to select it; a finger's tap on a stroke selects it with any tool. Drag inside the dashed box with the pen to move it; a straight line shows handles at its ends, which the pen moves. **Delete** (or the toolbar's bin) removes the selection. |
14
- | Laser pointer | A red dot with a white core and a short trail that disappears by itself, for pointing at something. With a pencil that can hover, the dot follows it without touching. Never kept. |
14
+ | Laser pointer | A red dot with a white core and a trail that stays as long as the pen or finger is down and disappears by itself once it is lifted, for pointing at something or circling it. With a pencil that can hover, the dot follows it without touching. Never kept. |
15
15
  | Eraser | Removes whole strokes you touch. |
16
16
 
17
17
  **Zoom**: two fingers zoom into the slide and move around it, one finger moves a zoomed slide, and Ctrl + scroll (a trackpad pinch) zooms on a laptop. Only the slide grows; the bars and the toolbar keep their size. The audience window shows the same part of the slide. **1:1** at the top left shows the whole slide again, as does the next slide. To zoom straight to a picture or a table with a number key, see [hotspots](presenting.html#zoom-in-on-part-of-a-slide).
@@ -47,7 +47,7 @@ There are two ways.
47
47
  **The iPad next to your laptop.** The laptop shows the slides on the projector; you draw and go through the slides on the iPad, with your notes on it.
48
48
 
49
49
  1. Start `mdeck run my-talk.md --network`, so the iPad in the same network can reach your laptop.
50
- 2. On the launch page, under **Present from an iPad**, choose **Show pairing code** and scan it with the iPad's camera. The presenter view opens on the iPad, paired with your laptop, so it may save drawings and steer the phones of a poll. It is the same presenter view as on the laptop; pairing only gives it these rights. Once it is open, the launch page says so.
50
+ 2. In the presenter view on the laptop, click the connection icons at its top, choose **iPad**, and scan the code with the iPad's camera. The presenter view opens on the iPad, paired with your laptop, so it may save drawings and steer the phones of a poll. It is the same presenter view as on the laptop; pairing only gives it these rights. Once it is open, the launch page says so.
51
51
  3. On the laptop, open the **audience window** from the same place and move it to the projector. It follows the iPad: slides, revealed points, drawings as you draw them, and videos. Navigation in the audience window also updates the iPad's slide, notes and next-slide preview.
52
52
 
53
53
  **Videos.** A video file on a slide (`<videoplayer src="…" />`) plays, pauses and jumps on the projector as you tap it on the iPad. The sound comes from the projector: while the audience window is open, the iPad's copy plays silently. Browsers start sound only on a page someone has clicked, so click the audience window once before the talk (going full screen counts); otherwise the video plays there without sound and shows **Click for sound**.
@@ -59,13 +59,13 @@ A pairing code works once, for ten minutes. **Unpair** on the launch page ends e
59
59
  **The iPad on another network.** Some networks, often big Wi-Fi networks at universities, do not let devices reach each other, and a laptop's firewall may not let the iPad in. With a server of your own (see [Ask your audience](audience.html#use-it-in-a-real-session)) the iPad does not need to reach your laptop at all: your laptop connects out to the server, and the server passes the iPad's requests to it. The slides are not uploaded or stored anywhere.
60
60
 
61
61
  1. Tell mdeck where your server is: `server: https://rooms.example.org` in the deck's settings, or `MDECK_SERVER` in your shell, or the address after the option in the next step.
62
- 2. Start `MDECK_SERVER_KEY=your-key mdeck run my-talk.md --server`. The key is the one the server was started with.
63
- 3. On the launch page, choose **Show pairing code** under **Present from an iPad** and scan it. The address in the code is on your server and contains a long random name, so treat it like a private link.
62
+ 2. Start `MDECK_SERVER_KEY=your-key mdeck run my-talk.md --server`. The key is the one the server was started with. With `MDECK_SERVER` and `MDECK_SERVER_KEY` both set in your shell, plain `mdeck run my-talk.md` is enough: it uses the server whenever it answers.
63
+ 3. In the presenter view on the laptop, click the connection icons, choose **iPad** and scan the code. The address in the code is on your server and contains a long random name, so treat it like a private link.
64
64
  4. Open the **audience window** on the laptop as before. It follows the iPad through the server.
65
65
 
66
66
  Everything else works as with `--network`: drawings are saved in the drawings file beside the deck, and the iPad may steer polls. Editing the slides on the laptop reloads the iPad too. The server only passes on what the presenter and audience pages need; the launch page, the editor and the other files in your folder are not reachable through it. Stopping `mdeck run` ends the connection, and a pairing code stops working when you unpair or stop.
67
67
 
68
- On a touch screen the presenter view shows only the slide, with a small bar at the top: timer, previous and next, draw, **Notes** (a drawer with your notes and the next slide, also **N**), full screen, and a button back to the layout with notes beside the slide. Your choice is remembered on that device.
68
+ On the iPad the presenter view shows only the slide, with one bar at the top: the slide number, the timer, previous and next, drawing, black screen, all slides, hotspots, the slide's own controls, the notes drawer (with the next slide, also **N**), who is connected and the settings. The settings switch the layout; each device remembers its choice.
69
69
 
70
70
  With a server of your own (the `server` setting, see [Ask your audience](audience.html)), the same also works with a hosted deck: open the presenter view on the iPad with your key (`?serverkey=…`), and the audience window anywhere else follows it. With the deck opened through `mdeck run` and the server's key set (`MDECK_SERVER_KEY`), the paired iPad and the audience window talk over your own network, and only the polls go through the server. Drawings are then kept on the iPad; download the drawings file after the talk.
71
71
 
@@ -1,38 +1,8 @@
1
1
  # Make your first presentation
2
2
 
3
- You will install mdeck, teach your AI assistant how to write mdeck slides, give it material you already have, and open the deck it makes. If mdeck is already installed, skip to “Teach your assistant about mdeck.”
3
+ You will give your AI assistant material you already have and open the deck it makes.
4
4
 
5
- ## Set up mdeck once
6
-
7
- mdeck needs Node.js and npm on your computer. Install [Node.js](https://nodejs.org) (version 22 or newer); npm comes with it.
8
-
9
- Open a terminal. A terminal is an app where you type short commands: Terminal on macOS, or PowerShell on Windows. A text editor may also have a Terminal menu.
10
-
11
- Run this command to install mdeck:
12
-
13
- ```sh
14
- npm install -g mdeck
15
- ```
16
-
17
- You normally do this only once. To update later, run it again.
18
-
19
- Check that the command is ready:
20
-
21
- ```sh
22
- mdeck --help
23
- ```
24
-
25
- If your computer does not recognize `npm` or `mdeck`, see [When something goes wrong](troubleshooting.html#the-command-is-not-recognized).
26
-
27
- ## Teach your assistant about mdeck
28
-
29
- mdeck comes with a set of instructions, called a *skill*, that tells an AI assistant how mdeck slides are written, which layouts and looks exist, and how to check its work. Install it for the assistant you use:
30
-
31
- ```sh
32
- mdeck skill --install claude
33
- ```
34
-
35
- Replace `claude` with `codex`, `cursor`, `copilot` or `gemini` for those tools. Run `mdeck skill` to see the list. For Cursor, Copilot and Gemini, run it in your talk's folder.
5
+ First [install mdeck](install.html) and the skill for your assistant, if you have not yet. It takes a few minutes.
36
6
 
37
7
  ## Hand over your material
38
8