Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .claude/skills/adding-a-thought/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ The voice is DESIGN.md "Wording": first person, short sentences, plain words, no
- Figures carry the ideas that are easier to see than to read. Use `figure.anim` (DESIGN.md "Animated diagram"): a drawing that plays once on screen, a two-state switch, parts to tap, a running token. Draw a narrow version (`.dg-n`) for phones. Use only the `.dg` classes, no colours, no `style` attributes.
- End with what Tim takes from it: a rule, a draft, a file, or open questions.

Write for a technical reader who does not know every concept. Tim's feedback on encrypted-patches (12 Nov 2026): the TUF and drand parts were too short and had too many new words, and the games and patents sections felt meaningless.

- Explain each new term where it first appears, in one plain sentence: what it is, then why it matters here. "A bug that is already fixed and public is called an n-day." A name alone (TUF, Uptane, drand, tlock) is not an explanation.
- Give a mechanism the room it needs. If the argument rests on it, explain how it works in a few short paragraphs, with an everyday comparison where one fits. Do not compress it into a list of terms.
- Every section must carry the argument. End a detour or an example with what it teaches for the idea ("So the lesson from games is four rules"). If it teaches nothing, cut it or fold it into the section it serves. Background such as patents gets one short paragraph with the practical consequence.
- Use few numbers in a row. After a dense list, say in one sentence what the numbers show.
- Check every new explanation against a primary source, like any other claim.
- If the thought will be read aloud, use the skill `narrating-a-thought` too. Text that reads well aloud also reads well on the page.

## 5. The page

Copy `thoughts/humans-md/index.html` and keep its structure:
Expand Down
79 changes: 79 additions & 0 deletions .claude/skills/narrating-a-thought/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: narrating-a-thought
description: Use when Tim wants a thought on t7d.dev read aloud, narrated, turned into audio or a podcast, given read-along highlighting, or explained by a voice. Also use when the narration script, the voice, the ElevenLabs audio, narration.json or assets/narration.js must change, or when a narrated page feels restless, hides its diagram on a phone, or loses the listener.
---

# Narrating a thought

A narrated thought works two ways from one recording: Tim reads and listens at the same time, or he listens on the go with the screen off. The voice tells more than the page: it explains every figure and bridges the sections. The page follows the voice calmly and never hides the figure that the voice explains.

The design was tested with Tim on 12 Nov 2026, first in a prototype, then on `thoughts/encrypted-patches/`, the reference page. Do not reopen these decisions unless Tim asks. The research behind them is in `attention-research.md`.

## Audio costs credits: generate only when Tim says so

- Generate ElevenLabs audio only when Tim says that the text of the thought is final and must be narrated. Approval of a cost estimate is not that instruction.
- Do not make voice samples. The voice is chosen (see the table).
- Until then, the page runs on simulated timing (about 160 words a minute). Tim reads along and judges the text, the spoken parts and the figures without audio.
- Do not read, print or commit the key. It is in `~/.config/wortzauber/elevenlabs.key`. Send it only as the `xi-api-key` header.
- Before a generation, tell Tim the character count. After it, tell him what it used.

## How it is built

| Part | Where |
| --- | --- |
| Player, marker, cues, scrolling | `assets/narration.js` (no inline script, the CSP stays strict). The page loads it with `<script src="/assets/narration.js" defer>` and needs `connect-src 'self'` in its CSP for the JSON. |
| Styles and the colour tokens | "Narration" in `assets/site.css`. DESIGN.md has the rules. |
| Opt-in | `<article class="prose" data-narration="/thoughts/<slug>/narration.json">` |
| The script | The page itself: every `h2`, `p` and `li` of the article up to `#sources`, in order, without source marks, plus the `.say` blocks. Figures, captions and code blocks are not read. |
| Spoken parts | `<div class="say" id="say-..."><p><span class="say-k">Spoken</span>...</p></div>` in the page. `data-pause="2.5"` adds silence after it. A spoken part with several paragraphs wraps them in one `<div>`: the fold closes only one grid row, and a second paragraph would leave an empty space. |
| Colour blocks | `<span class="mk" data-c="red|green|blue|yellow">term</span>` in the text. It turns on when the voice reaches its first word. Nothing else is needed. |
| `narration.json` | `title`, `voice`, `audio` (mp3 path or null), `timing` (`{start: [...], end: [...]}` per character of the script, or null for simulated), `chapters` (`[id, title]`, id of an `h2` or a `.say`), `spoken` (id to spoken form, where TTS must hear other words than the page shows), `cues`. |
| Figure cues | `{"in": "say-fig1", "p": "phrase in the script", "until": "phrase", "sel": ".cue-find", "cls": "hot"}`. `sel` is looked up inside the figure of `in`. `hot` makes that part stand out while the rest of the figure steps back. Without `cls`, the part gets `on`, and `[data-c].on` fills with its colour. Without `until`, the cue stays on. |
| Step figures | Use `figure[data-voice-steps]`, not `data-steps`: no step box and no Back, Next or Play buttons, because they compete with the voice. Parts of the drawing carry `data-step="n"`. Under the drawing is a plain `<ol class="fig-steps">` with `<li value="n">` (the value keeps the number when the other items hide). `narration.js` brings in the parts of the step that the voice reads. When only reading, the whole drawing and the whole list show. |
| Switch and pick figures | Not driven by the voice yet (`data-switch`, `data-pick`). Use `hot` cues on their parts, and describe both states of a switch in order. To let the voice flip a switch, add an event to `site.js` like `narration:step`, and ask Tim first. |

## Decided design

| Part | Decision |
| --- | --- |
| Voice | Jonathan Livingston, ElevenLabs library, `PIGsltMj3gFMR34aFDI3`, rate 1.0. Model `eleven_multilingual_v2`, stability 0.5, similarity 0.75, style 0.1, speaker boost on. Eric (`cjVigY5qzO86Huf0OWal`) is the second choice. |
| Generation | `POST /v1/text-to-speech/{voice}/with-timestamps?output_format=mp3_44100_96`. The model takes at most 10,000 characters per request, so make one request per chapter with `previous_text` and `next_text`. Join the mp3 files and offset the character timings into one `timing` for the whole script. |
| Spoken parts | An intro (title, author, length, the 2 or 3 key terms, "figures are described"). A bridge only where the argument jumps between sections, never where a section opens with its own bridge sentence. A walk-through per figure. A short summary after a dense list of numbers. One pause question at the end of a long section (at most two per thought). An outro that sums up in two or three sentences. |
| Figure walk-through | What kind of drawing, its structure, each part in a fixed order, then the takeaway. Describe it so that it fits both the wide and the narrow drawing: "three parts", "the top row", not "on the left". Split a long walk-through into paragraphs of at most about 60 words. For a step figure, a short intro, then the step items carry it. |
| Marker | A grey tint (`--ink` at 16%) over a phrase of up to 7 words, cut at punctuation or at a pause over 0.5 s. It moves about every 2 s. Words go from 50% to full opacity as they are spoken. No per-word block. |
| Colours | Red: problem. Green: Tim's own idea. Blue: prior work and sources. Yellow: a term to remember. About three per section. |
| Other blocks | Dim by text colour, never by `opacity`. Opacity faded the colour blocks until their text disappeared. |
| Figures on a phone | Every wide figure needs a narrow drawing (`.dg-n`, 360 wide, same `data-step` and cue classes). Under a figure, only the paragraph that the voice reads shows, and the caption waits. The page scrolls the whole figure into the space between the site header and the player. |
| Player | Strip at the bottom: play, back (to the start of the sentence, or the one before), forward 15 s, chapter and time (tap: chapters, "Show all spoken parts"), speed 1, 1.15, 1.3, 0.9. No 2x. After a pause of more than 30 s, play starts at the beginning of the sentence. |
| Offline, podcast | A PWA (service worker, manifest) changes the rule "only theme.js and site.js" in CLAUDE.md. A podcast feed or an mp3 download is public. Ask Tim before any of these. |

## Writing the text for a narrated thought

Use the skill `adding-a-thought` for the text. Then:

1. Mark about three terms per section with `.mk`.
2. Add the spoken parts as `.say` blocks at their places.
3. Write the chapters and the figure cues into `narration.json`.
4. Draw a narrow version of every wide figure.

## Check before you report

- `python3 scripts/check.py` passes. `node --check assets/narration.js` passes.
- Serve the site. At 412 x 780 in light and dark, click into every figure paragraph and every step: the figure must sit between the header and the player. Measure it with a script.
- No sideways scroll at 1440, 390 and 320 px. No console errors.
- No label of a narrow drawing leaves its box or the frame. Check it with `getBBox()`.
- Show it as an artifact with `scripts/preview-artifact.py`. Say that the timing is simulated, or that you cannot judge the sound.

## Mistakes that happened

| Mistake | Fix |
| --- | --- |
| A solid block on every word: about 3 moves per second and a black/white flash per word felt restless. | The phrase marker. |
| A caption box for audio-only text broke the reading. | Folded spoken parts in the text. |
| The whole figure description under the figure pushed the drawing off the phone screen. | One paragraph under the figure, caption hidden, narrow drawing. |
| A walk-through said "on the left" while the phone showed a stacked drawing. | Layout-neutral words. |
| The sticky site header covered the top of the framed figure. | Subtract the header height when scrolling. |
| A wide drawing scrolled sideways inside its box, so half of it was out of view. | A narrow drawing. |
| The manual step viewer (box, Back, Next, Play, "Step 2 of 5") stayed under a narrated figure and broke the immersion. | Voice steps: a plain list, the voice animates. |
| Empty space under a figure: a second paragraph in a spoken part kept its height, and a folded part in the figure grid still added one gap. | One wrapper per spoken part. Folded parts in a figure use `display: none`. Measure the space from the drawing to the next element before and after Listen. |
| A python `http.server` cannot seek in an mp3 (no range requests). | Load the audio as a blob. |
39 changes: 39 additions & 0 deletions .claude/skills/narrating-a-thought/attention-research.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Attention research for narrated thoughts

What research says about holding a listener's and a reader's attention, and what each finding means for a narrated thought. Checked on 12 Nov 2026. Where only a summary or abstract was read, the entry says so.

## Findings

| Finding | Evidence | What it means here |
| --- | --- | --- |
| People learn more from a picture with spoken words than from a picture with printed words (modality principle). | Fiorella and Mayer 2022, review of 76 studies, median d = 0.65 [1]. | Let the voice explain the figure. Do not put the same explanation as text next to the figure. |
| Printed text that repeats the narration word for word, next to a picture, hurts learning (redundancy principle). It does not hurt when the text is very short. | Mayer's reviews, d about 0.7 to 0.87 [2][3]. | Spoken parts stay folded until the voice reaches them. Under a figure, show only the paragraph that the voice reads now, not the whole description. |
| Cues that show what matters help (signaling). | Mayer's reviews, d about 0.46 to 0.69 [2][3]. | The four colours and the phrase marker are cues. A cue must point at what the voice says now, and at nothing else. |
| Learner-paced segments beat one continuous stream (segmenting). | Mayer's reviews, d = 0.70 [2]. | Chapters, skip 15 s, tap a paragraph to play from there. |
| Interesting but irrelevant extras lower learning, more so in short lessons (seductive details). | Rey 2012. Sundararajan and Adesope 2020, 68 experiments. A 2026 multi-level meta-analysis, g = -0.16 [4]. Summaries only. | Bridges carry the argument forward. No jokes, anecdotes or sound effects that do not serve the point. |
| Synchronized word highlighting captures the eyes, but it did not improve children's learning over unsynchronized reading while listening. Weaker readers liked it most. | Gerbier, Bailly and Bosse 2018 [5]. Abstract and summaries only. | A strong word-by-word marker pulls the eye and does not teach more. Use a calm phrase marker. This matches what Tim felt with the solid word block. |
| Reading while listening helps weaker readers and doubled reading volume in one study. Results on comprehension are mixed. | Review of reading-while-listening studies [6]. | The read-along mode is a reason to read, not proof of better understanding. Keep audio-only listening a full experience too. |
| Listening alone produced more mind wandering, weaker memory and less interest than reading aloud or silent reading. | Varao Sousa, Carriere and Smilek 2013 [7]. In everyday settings, outside distraction mattered more than mind wandering (2018) [8]. | Pure listening needs extra help: signposts, short recaps, an outro. Readers on a phone get distracted, so resume and "Back to the voice" matter. |
| Short tests during a lecture halved mind wandering (40% without them) and improved retention. | Szpunar, Khan and Schacter 2013, PNAS, 21-minute lecture [9]. | Open idea: a short question at a section end ("Pause here: which file reads you?"). Not tried yet. |
| Shorter videos held viewers longer. | Guo, Kim and Rubin 2014, 6.9 million sessions on edX [10]. The often quoted "6 minutes" comes from summaries, not checked in the paper. | Keep chapters short, about 1 to 3 minutes. Show the length of each chapter. |
| Narration is usually 150 to 160 words per minute. Listeners picked about 165 wpm as comfortable. Comprehension holds up to about 1.25x and drops near 1.5x to 2x. | Production norm and summaries of speech-rate studies [11]. One ad study found about 180 wpm best [11]. | Default 1x, offer 0.9x, 1.15x and 1.3x. Do not offer 2x. |
| A modern synthetic voice taught as well as a human voice. The human voice still felt more human and engaging. | Craig and Schroeder 2017; Mayer and DaPra 2012 [12]. Summaries only. | ElevenLabs is fine for learning. Choose a calm voice with a natural pace. Keep the same voice for all thoughts, so it becomes familiar. |
| Writing for the ear: short sentences of varied length, one idea per sentence, signposts and previews, deliberate repetition of the main point. | Radio and NPR training material [13]. Practice guidance, not experiments. | Bridges preview the next question. Repeat the key term when a section returns to it. |
| Describe a diagram by its point, not by every detail. Long narrated descriptions of flow charts are hard to follow. Present processes as ordered steps. | WGBH/NCAM guidelines for STEM images; OCALI audio description tips [14]. | Figure walk-through: kind of drawing first, then axes or structure, then each part in a fixed order, then the takeaway. |

## Sources

1. Fiorella and Mayer 2022, modality principle review, summarised in Mayer, Multimedia Principles (2020/2021): https://ugc.futurelearn.com/uploads/files/7d/d6/7dd6188d-c343-4311-b064-ac98d2c95abc/Multimedia_Principles._R._E._Mayer__2020.pdf
2. Mayer 2017, Using multimedia for e-learning, Journal of Computer Assisted Learning: https://zendy.io/title/10.1111/jcal.12197
3. Dartmouth summary of Mayer's principles: https://services.dartmouth.edu/TDClient/1806/Portal/KB/PrintArticle?ID=171655
4. Seductive details overview: https://en.wikipedia.org/wiki/Seductive_details and https://www.learningandthebrain.com/blog/seductive-details-when-do-cool-stories-and-videos-interfere-with-learning/
5. Gerbier, Bailly and Bosse 2018: https://hal.archives-ouvertes.fr/hal-01575227
6. Reading while listening review (LUCS 176): https://www.lucs.lu.se/fileadmin/user_upload/project/lucs/LUCS-pub/LUCS-176.pdf
7. Varao Sousa, Carriere and Smilek 2013, Frontiers in Psychology: https://pmc.ncbi.nlm.nih.gov/articles/PMC3842750
8. Varao-Sousa, Smilek and Kingstone 2018: https://pmc.ncbi.nlm.nih.gov/articles/PMC6246756
9. Szpunar, Khan and Schacter 2013, PNAS: https://pmc.ncbi.nlm.nih.gov/articles/PMC3631699
10. Guo, Kim and Rubin 2014: https://up.csail.mit.edu/other-pubs/las2014-pguo-engagement.pdf
11. Speech rate: https://psychologytoday.com/au/blog/small-talk-and-big-questions/202307/is-speed-listening-right-for-you and https://cdn.warc.com/newsandopinion/news/how-speech-delivery-speed-impacts-audio-ads/43304
12. Voice principle: https://unpaywall.org/10.1016%2Fj.compedu.2019.103756
13. Writing for the ear: https://www.npr.org/sections/npr-training/2025/05/30/g-s1-65814/the-journey-from-print-to-radio-storytelling-a-guide-for-navigating-a-new-landscape
14. WGBH guidelines for describing STEM images: https://www.wgbh.org/guidelines-for-describing-stem-images ; OCALI tips: https://conference.ocali.org/up_doc/2024_Tips_AD.pdf
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ t7d.dev: the personal site of Tim Conrad. Plain HTML, CSS and a little JavaScrip
- A new tool page: copy `tools/papercuts/index.html`, keep its `<!-- tool-readme: owner/name -->` placeholder, and add the tool to `tools/index.html`, the Tools section of `index.html` and `sitemap.xml`. `scripts/gen-tools.py` puts the README of the latest release into the page at deploy time. Never paste a README by hand. Test: `uv run --no-project --with markdown==3.11.3 python3 -m unittest scripts/test_gen_tools.py`.
- `drafts/` holds local drafts. Git ignores it, and it is not in `SITE` or `sitemap.xml`. The repo is public, so a draft never goes into git. To publish a draft, move it to its real folder.
- A new or revised thought: use the skill `adding-a-thought`. `llms.txt` and the feeds are made at deploy time (`scripts/gen-feeds.py`); do not commit them.
- Keep the Content-Security-Policy of each page strict: no inline scripts or styles, no `style=""` attributes, and no request to another site on page load. `assets/theme.js` and `assets/site.js` are the only scripts, plus the characters of each game page (`assets/play/play-kb.js`, `assets/play/play-wz.js`; see "Game pages" in `DESIGN.md`).
- Keep the Content-Security-Policy of each page strict: no inline scripts or styles, no `style=""` attributes, and no request to another site on page load. `assets/theme.js` and `assets/site.js` are the only scripts, plus the characters of each game page (`assets/play/play-kb.js`, `assets/play/play-wz.js`; see "Game pages" in `DESIGN.md`), and `assets/narration.js` on a narrated thought (skill `narrating-a-thought`).
- `master` is the source. Never edit `gh-pages` by hand: the workflow publishes it after every push to `master`, and the sealed admin app (`Tim-Conrad/sealed`) publishes encrypted sites to `sealed/` on it, a folder that exists only there. `scripts/deploy.sh` must keep `sealed/`.
- Classes and scripts that the sealed login page uses (`.sealed`, `.label`, `.btn`, `.nav`, `#theme-toggle`, `/assets/site.js`) are used by another repository too. Keep them, or change `client/themes/t7d/login.html` in sealed with them.
- `blog/` and `CVE/` only redirect old addresses (the thoughts were a blog until November 2026). Do not add pages there.
Expand Down
Loading
Loading