Development¶
Setup¶
Commands¶
make build # type-check and build the extension into dist/
make dev # rebuild the settings panel on every save
make install # bump the patch version, build, copy to your install folder
make package # zip dist/ into release/earsup-vX.Y.Z.zip
make docs # serve these docs at http://127.0.0.1:8000
make release-notes-init # create docs/releases/vX.Y.Z.md from the template
make release # tag, push, and publish a GitHub release with the zip
After make build, load dist/ with Load unpacked in chrome://extensions. After a change, click the reload arrow on the EarsUp card and refresh the page.
make install copies the build to $EARSUP_INSTALL_DIR. Set it to the folder Chrome loads EarsUp from, for example:
Project layout¶
public/ manifest.json, icons, bunny artwork (copied into dist/ as is)
src/background/ service worker: Gemini calls, history, side panel, shortcuts
src/content/ runs on every page: play buttons, reading, player, follow-along
src/options/ React settings panel (General, Voices, Sites, History, About)
src/shared/ settings, site rules, text chunking, tooltips
scripts/ release and docs helpers
docs/ this site (MkDocs Material)
media/ screenshots and artwork for the README, docs, and releases
The settings panel is built as a normal Vite page. The content script and the service worker are each built as one IIFE file (vite.scripts.config.ts), because Chrome does not load ES modules in content scripts.
How reading works¶
- The content script finds headings, and draws play buttons in a shadow DOM overlay. The page DOM is not changed.
- On play, it walks the page from the heading to the next heading of the same level or higher. It collects the visible text and keeps a map from each character back to its text node.
- The text is split into paragraphs, then into parts of one or two sentences.
- Chrome voices use
speechSynthesis. Theirboundaryevents drive the word highlight. Gemini voices are fetched by the service worker, and the word is estimated from audio progress. - The sentence and word are painted with
CSS.highlights, using the character map.
Docs¶
The docs use MkDocs Material. They deploy to GitHub Pages from .github/workflows/docs.yml on every push to main that touches docs/, media/, or mkdocs.yml.
docs/media is a link to media/, so the README, the docs, and the release notes share the same images.
Releases¶
make release-notes-init VERSION=v1.2.3and fill indocs/releases/v1.2.3.md. Write images asIMG:media/file.png.- Add the new page to the
Releasesnav inmkdocs.yml. - Set
"version"inpublic/manifest.jsonandpackage.jsonto1.2.3, and commit. make release VERSION=v1.2.3. This builds, zips, tags, pushes, and publishes the GitHub release with the zip attached.IMG:links become raw GitHub URLs in the release, and relative paths on the docs site.