A BeeLine reader extension that doesn't suck ass.
Buzzline applies eye-guiding color gradients to text on every webpage so your eye is pulled smoothly from the end of one line to the start of the next.
- Open
chrome://extensions. - Enable Developer mode (top right).
- Click Load unpacked and select this project folder.
- Pin the Buzzline icon, click it, and flip the switch on.
The content script:
- Walks every text node in the page (skipping
<script>,<code>, inputs, and page chrome —<nav>,<header>,<footer>,<aside>, ARIA navigation/banner/complementary/search roles, and elements whose class or id contains junk tokens likenav,sidebar,ad,banner,promo,comment,share,byline,pagination,cookie, etc.). - Wraps each remaining character in a
<span data-bzln>so each glyph is independently colorable. - Groups spans into visual lines using
getBoundingClientRect()— a new line starts when the top coordinate jumps more than ~60% of a glyph's height or when we cross into a new block-level ancestor. - For line index
i, interpolates the color of each span along the line between palette colori mod Nand color(i+1) mod N. The end color of each line therefore matches the starting color of the next. - Reapplies on window resize (the line grouping changes when text reflows)
and watches the DOM with a
MutationObserver(childList + characterData) to handle dynamic content.
Per-site opt-out: the popup shows the current hostname and a "Disable on
this site" toggle. Hostnames you opt out of are stored in
chrome.storage.sync under disabledHosts and are skipped even when the
global switch is on.
Colors are applied via a CSS custom property (--bzln-c) read by a rule in
content.css. That rule carries !important so it overrides site CSS; the
extension-declared stylesheet is not subject to page CSP.
Text is split on grapheme clusters via Intl.Segmenter, so emoji, flags,
and ZWJ sequences stay intact.
Every colored block gets a small yellow launcher icon at its start. Click it to open Sprint — an RSVP overlay that flashes one word at a time with the Optimal Recognition Point (ORP) highlighted in red and horizontally aligned on a fixed guide so your eye stays still.
Controls: play/pause (space), prev/next word (← / →), close (Esc), speed slider (150–900 WPM, default 500). Punctuation and long words get proportionally longer holds so you can catch clause boundaries.
Preset palettes cycle through four colors — each line starts in one and ends in the next, so adjacent lines share a handoff color:
- Classic — black / blue / black / red
- Dark mode — light gray / light blue / light gray / peach
- Ocean — navy / teal / navy / seafoam
- Bumblebee — near-black / gold / near-black / brown
- High contrast — black / pure blue / black / pure red
- Per-character spans on very long articles (10k+ characters) use measurable memory and add a small layout cost. Fine on normal pages; heavy pages may flash briefly while processing.
- Does not descend into iframes or shadow DOM in this release.
- Code blocks, inputs, and contenteditable regions are intentionally left alone.
- Vertical writing modes (
writing-mode: vertical-rletc.) are detected and skipped — those blocks stay their original color. - Pages with very strict CSP (
style-srcexcluding'unsafe-inline') may block the inline custom-property assignment. The base rule still loads, so spans fall back toinheritand look normal (just uncolored).
manifest.json Chrome MV3 manifest
src/content.js Per-char span + gradient engine + Sprint launchers
src/sprint.js RSVP reader overlay (ORP-aligned word flashing)
src/content.css Base CSS + launcher + Sprint overlay styles
src/popup.html/css/js Toolbar popup (toggle, scheme picker, live preview)
icons/ Extension icons (cropped from assets/logo.png)
scripts/gen_icons.py Regenerates the icons (Pillow)
- No build step. Edit files, reload the extension in
chrome://extensions, reload the page. - State lives in
chrome.storage.syncunder the keysenabled,scheme, anddisabledHosts(array of hostnames to skip). - To regenerate icons:
python3 scripts/gen_icons.py.
BeeLine Reader's gradient technique is covered by US Patent 9,026,907. Personal/educational use is generally fine; consult a lawyer before distributing publicly.