Summary
Create a reusable html-read-aloud skill that adds in-browser narration and synchronized scrolling to standalone HTML documents. Integrate it with readable-html-dossier so generated dossiers can optionally include a self-contained reading controller without requiring a server, browser extension, framework, or build step.
The narration feature should remain a separate composable skill rather than expanding readable-html-dossier into a large mixed-purpose skill.
Motivation
readable-html-dossier already produces semantic, standalone HTML files and opens them directly through a file:// URL. This makes it a good host for an inline reader powered by the browser's native Web Speech API.
The desired experience is:
Open a generated dossier in the browser.
Press Read aloud .
Hear the document narrated block by block.
See the active block highlighted and automatically scrolled into view.
Pause, resume, stop, or move between blocks.
Architectural decision
Add a new skill:
.agents/skills/html-read-aloud/
├── SKILL.md
└── REFERENCES.md
html-read-aloud owns:
narration controls
semantic content extraction
speech queue management
active-block highlighting
synchronized scrolling
persistence of reader preferences/progress
accessibility requirements
readable-html-dossier continues to own:
document structure
typography and readability
themes
print styles
report-generation workflow
The dossier skill should invoke or reference html-read-aloud when narration is requested. Once stable, narration may become the default for interactive dossiers, with an explicit opt-out.
Proposed integration contract
Update readable-html-dossier/SKILL.md with guidance similar to:
When a dossier should support narrated reading, load /html-read-aloud and embed its standalone controller. Narration must work from a file:// URL and must not require a server or build step.
Generated HTML should expose a predictable reading root:
< article data-readable-root >
...
</ article >
Optionally allow explicit inclusion/exclusion:
< section data-readable > ...</ section >
< pre data-reader-ignore > ...</ pre >
< nav data-reader-ignore > ...</ nav >
V1 scope
Content extraction
Build a deterministic list of readable blocks from the document root.
Default readable selectors:
h1, h2, h3, h4, p, li, blockquote, figcaption, td, th
Default ignored content:
script, style, nav, button, input, select, textarea,
[hidden], [aria-hidden="true"], [data-reader-ignore], pre, code
Rules:
Ignore empty or whitespace-only blocks.
Avoid reading nested elements twice.
Preserve semantic order from the DOM.
Collapse excessive whitespace.
Do not narrate raw URLs unless they are the meaningful visible text.
Code blocks are excluded by default but may be explicitly enabled later.
Speech model
Use window.speechSynthesis and SpeechSynthesisUtterance.
Use one utterance per semantic block rather than one utterance for the entire document.
Reasons:
more reliable synchronization
simple previous/next navigation
clean pause boundaries
easier progress persistence
no dependency on inconsistent word-boundary events
For each block:
Create an utterance from normalized textContent.
On start, mark the corresponding element active and scroll it into view.
On end, advance to the next block.
On error, surface a non-blocking status and stop safely.
Reader controls
Add a compact floating controller containing:
Play / resume
Pause
Stop
Previous block
Next block
Playback-rate selector
Voice selector
Auto-follow toggle
Progress indicator, for example 12 / 84
Recommended keyboard shortcuts:
Shortcut
Action
Space
Play/pause when focus is in the reader controller
Escape
Stop narration
Alt+ArrowLeft
Previous block
Alt+ArrowRight
Next block
Do not hijack keyboard input while the user is typing in a form control.
Highlighting and scrolling
Apply an active class or attribute:
< p data-reader-active ="true "> ...</ p >
Expected behavior:
Highlight the active block with a subtle background/border treatment.
Use scrollIntoView({ behavior: "smooth", block: "center" }) when auto-follow is enabled.
Respect prefers-reduced-motion; use instant scrolling when reduced motion is requested.
Avoid continuous forced scrolling if the user manually scrolls away.
Provide an explicit auto-follow toggle to re-enable centering.
State management
Model the reader as a small state machine:
idle -> playing -> paused -> playing
playing -> stopped
playing -> completed
any state -> error
Suggested state:
{
blocks : HTMLElement [ ] ,
currentIndex : number ,
status : "idle" | "playing" | "paused" | "stopped" | "completed" | "error" ,
rate : number ,
voiceURI : string | null ,
autoFollow : boolean
}
Always call speechSynthesis.cancel() before starting a new queue to prevent overlapping narration.
Persistence
Use localStorage with a document-specific key derived from the pathname/title.
Persist:
selected voice URI
playback rate
auto-follow preference
last completed block index
Do not auto-start narration on page load. Browser autoplay/user-gesture restrictions should be respected.
Accessibility
Controls must be keyboard operable.
Every icon-only control must have an accessible label.
Status updates should use a restrained aria-live="polite" region.
Active highlighting must not rely on color alone.
Focus indicators must remain visible.
The controller must remain usable at 200% zoom and narrow laptop/mobile widths.
Print styles must hide the controller and active-reading decoration.
Privacy and dependencies
V1 must:
run entirely in the browser
use the browser's installed/native voices
make no network requests for narration
require no external JavaScript dependencies
work from a local file:// URL
Cloud TTS, generated audio, and server-side timestamp alignment are explicitly out of scope for V1.
Suggested skill contents
html-read-aloud/SKILL.md
Document:
when to use the skill
required HTML semantics
extraction rules
required controls
speech queue behavior
synchronization behavior
accessibility requirements
file:// constraints
verification checklist
html-read-aloud/REFERENCES.md
Include a reusable implementation scaffold with:
CSS for the controller and active block
semantic controller markup
dependency-free JavaScript implementation
content extraction helper
voice-loading behavior, including voiceschanged
queue/state management
localStorage persistence
reduced-motion handling
cleanup on beforeunload
The reference implementation should be designed for agents to embed directly into generated standalone HTML.
Implementation phases
Phase 1: functional prototype
Create the new skill files.
Implement block extraction.
Implement play, pause, stop, previous, and next.
Highlight and scroll to the active block.
Verify operation from a local file:// URL in Edge/Chromium.
Phase 2: reusable integration
Update readable-html-dossier to reference the new skill.
Add the data-readable-root convention to the dossier scaffold.
Add opt-in/opt-out instructions.
Ensure PR, Linear, and code-review dossier skills inherit the behavior through readable-html-dossier rather than duplicating it.
Phase 3: polish
Voice and rate selectors.
Preference/progress persistence.
Manual-scroll/auto-follow behavior.
Keyboard shortcuts.
Responsive and accessibility refinements.
Acceptance criteria
A new html-read-aloud skill exists and is independently reusable.
A generated standalone HTML file can narrate itself from a file:// URL.
Narration progresses block by block in DOM order.
The active block is visibly highlighted.
The active block scrolls into view when auto-follow is enabled.
Play, pause, resume, stop, previous, and next work without overlapping speech.
Voice and playback rate can be changed.
Reader preferences and progress survive a page refresh.
Controls are keyboard accessible and usable at 200% zoom.
Reduced-motion preferences are respected.
Code, navigation, controls, and explicitly ignored regions are not narrated by default.
The controller is hidden when printing.
No server, build step, framework, browser automation, or external JS dependency is required.
readable-html-dossier documents how and when to compose the new skill.
Existing dossier-producing skills can gain narration without copying implementation instructions.
Test plan
Test with a generated dossier containing:
multiple heading levels
long and short paragraphs
ordered and unordered lists
cards and callouts
tables
links
code blocks
hidden and ignored regions
dark and light themes
Verify at minimum in the user's primary browser, Microsoft Edge on Linux, and one additional Chromium browser if available.
Manually verify:
pause/resume in the middle of a block
stop and restart
previous/next at document boundaries
switching voices after voices load asynchronously
refreshing and restoring progress
manual scrolling while narration continues
print preview
200% zoom
reduced-motion mode
Non-goals for V1
word-by-word karaoke highlighting
cloud-generated or premium AI voices
audio-file export
sentence-level timestamps from a server
cross-device progress synchronization
automatic narration on page load
browser extension support
Future enhancements
opt-in code-block narration with language-aware preprocessing
sentence-level highlighting where browser support is reliable
cloud TTS adapters with cached audio and timestamps
chapter navigation from document headings
estimated time remaining
pronunciation overrides for technical terms and acronyms
Summary
Create a reusable
html-read-aloudskill that adds in-browser narration and synchronized scrolling to standalone HTML documents. Integrate it withreadable-html-dossierso generated dossiers can optionally include a self-contained reading controller without requiring a server, browser extension, framework, or build step.The narration feature should remain a separate composable skill rather than expanding
readable-html-dossierinto a large mixed-purpose skill.Motivation
readable-html-dossieralready produces semantic, standalone HTML files and opens them directly through afile://URL. This makes it a good host for an inline reader powered by the browser's native Web Speech API.The desired experience is:
Architectural decision
Add a new skill:
html-read-aloudowns:readable-html-dossiercontinues to own:The dossier skill should invoke or reference
html-read-aloudwhen narration is requested. Once stable, narration may become the default for interactive dossiers, with an explicit opt-out.Proposed integration contract
Update
readable-html-dossier/SKILL.mdwith guidance similar to:Generated HTML should expose a predictable reading root:
Optionally allow explicit inclusion/exclusion:
V1 scope
Content extraction
Build a deterministic list of readable blocks from the document root.
Default readable selectors:
Default ignored content:
Rules:
Speech model
Use
window.speechSynthesisandSpeechSynthesisUtterance.Use one utterance per semantic block rather than one utterance for the entire document.
Reasons:
For each block:
textContent.start, mark the corresponding element active and scroll it into view.end, advance to the next block.error, surface a non-blocking status and stop safely.Reader controls
Add a compact floating controller containing:
12 / 84Recommended keyboard shortcuts:
SpaceEscapeAlt+ArrowLeftAlt+ArrowRightDo not hijack keyboard input while the user is typing in a form control.
Highlighting and scrolling
Apply an active class or attribute:
Expected behavior:
scrollIntoView({ behavior: "smooth", block: "center" })when auto-follow is enabled.prefers-reduced-motion; use instant scrolling when reduced motion is requested.State management
Model the reader as a small state machine:
Suggested state:
Always call
speechSynthesis.cancel()before starting a new queue to prevent overlapping narration.Persistence
Use
localStoragewith a document-specific key derived from the pathname/title.Persist:
Do not auto-start narration on page load. Browser autoplay/user-gesture restrictions should be respected.
Accessibility
aria-live="polite"region.Privacy and dependencies
V1 must:
file://URLCloud TTS, generated audio, and server-side timestamp alignment are explicitly out of scope for V1.
Suggested skill contents
html-read-aloud/SKILL.mdDocument:
file://constraintshtml-read-aloud/REFERENCES.mdInclude a reusable implementation scaffold with:
voiceschangedbeforeunloadThe reference implementation should be designed for agents to embed directly into generated standalone HTML.
Implementation phases
Phase 1: functional prototype
file://URL in Edge/Chromium.Phase 2: reusable integration
readable-html-dossierto reference the new skill.data-readable-rootconvention to the dossier scaffold.readable-html-dossierrather than duplicating it.Phase 3: polish
Acceptance criteria
html-read-aloudskill exists and is independently reusable.file://URL.readable-html-dossierdocuments how and when to compose the new skill.Test plan
Test with a generated dossier containing:
Verify at minimum in the user's primary browser, Microsoft Edge on Linux, and one additional Chromium browser if available.
Manually verify:
Non-goals for V1
Future enhancements