kevinmichaelchen/selfdoc

πŸ“ A document that edits itself β€” MDX where the rendered page is the editor

0

stars

31

commits

JavaScript

primary language

Aug 16, 2026

updated

kevinmichaelchen.github.io/selfdoc/

README

selfdoc

Ask DeepWiki

A document that edits itself.

Click a paragraph. Type. Click away. Your edit is converted back to markdown and spliced into the .mdx source file at the exact character range that paragraph came from.

No CMS. No database. No admin panel. git diff is the audit log.

Edit mode: click a paragraph and type

The trick

Every markdown compiler knows where each block lives in the source file, down to the character β€” and then throws that away. We keep it.

  1. A tiny plugin stamps each rendered block with its source range.
  2. Clicking a block makes it editable in place.
  3. On blur, the HTML converts back to markdown and splices into the file at that exact range.

Everything else falls out of that loop. Adding a paragraph? A splice with an empty range. Deleting one? A splice with an empty replacement. The hover toolbar is just those splices with buttons on.

Run it

pnpm install
pnpm dev

Write in content/*.mdx. Every doc gets a card on the home page.

What's inside

✏️ Edit β€” prose is editable in the page: paragraphs, headings, lists, quotes, even text inside components. Bold, links, code, and citations survive the round trip.

πŸŽ™ Narration β€” you're forced to hear your own prose. Hover a section, hit the mic, and a 3-second countdown drops you into a live take with a waveform of your voice β€” then you listen back before keeping it. Silence is trimmed automatically. A small speech model (on your machine, dev only) pins every word to its moment, so playback highlights the word being spoken and skips your pauses. Rewrite a sentence and its audio goes stale until you read it again. Readers get a β–Ά that plays from any section onward.

πŸ”Š Synthetic voice β€” sections you haven't read yet can be filled by a local TTS model (Kokoro-82M, Apache-2.0, ~92 MB), rendered once on your machine from the Voice panel β€” which shows what your hardware can run, and the model's size, engine, and license before anything downloads. Synthetic takes are visibly marked, never count as your reading, and are replaced the moment you record the section yourself. Emoji are spoken sensibly or skipped. The full model landscape we evaluated lives in docs/tts-models.md.

✍ Provenance β€” proof of care, measured. Sessions, days, active time (idle tabs count nothing), edits landed, words moved, and typed-vs-pasted keystrokes β€” pasting a wall of generated prose leaves a visible signature. Stored in git beside the source; ships with every export.

πŸ’¬ Comments β€” feedback at any zoom: a phrase (select it first), a block, a section, or the whole doc. Reactions, grades, and a sidebar listing everything in document order. One click exports it all as JSON β€” with the text each comment targets β€” ready to hand to an agent. Lives in the reader's browser, never in the file.

⧉ Copy as markdown β€” the whole source, one click, straight to your agent's context window.

Plus the quiet stuff: a table of contents with per-section read times, a reading-progress ring, Tufte-style margin notes, footnote citations, and a 🌑 writing-lint mode (parked behind a flag while we rethink it).

Ship it

pnpm export                # one self-contained HTML file
DOC=colophon pnpm export   # any doc by name
AUDIO=1 pnpm export        # narration inlined (topbar dropdown does this too)

Exports carry only that doc β€” other drafts stay out of the bundle. Works from file://. Editing never ships. Pushes to main deploy the whole site to GitHub Pages, narration included.

The rules that keep it sane

WhatLives inBecause
Prosethe pageediting where you read
Structure & propsthe .mdx filestructure belongs in source
Reader feedbackthe reader's browsermarginalia isn't the document
Provenance & audiogit, beside the sourceproof should travel
TOC, read times, heatderived at rendercan never drift from the source

One rule above all: nothing gets a second home. The file is the document; everything else is derived from it or deliberately kept out of it.

Honest limits

Component props aren't inline-editable yet, tables and endnotes are file-edited, rewriting a block orphans its comments and audio (reverting revives them), and feedback is single-reader until the sync server exists. All tracked in ROADMAP.md, along with the gated local-model reading assistant.

Standing on

  • TiddlyWiki β€” proved a document can be its own editor, twenty years ago.
  • MDX + remark β€” whose source positions are the load-bearing fact here.
  • turndown β€” the way back from HTML to markdown.
  • Tufte β€” the margin notes.
  • TinaCMS β€” the productized cousin, and the off-ramp if this ever needs multi-user editing.

Contributors

kevinmichaelchen/selfdoc

πŸ“ A document that edits itself β€” MDX where the rendered page is the editor

0

stars

31

commits

JavaScript

primary language

Aug 16, 2026

updated

kevinmichaelchen.github.io/selfdoc/

README

selfdoc

Ask DeepWiki

A document that edits itself.

Click a paragraph. Type. Click away. Your edit is converted back to markdown and spliced into the .mdx source file at the exact character range that paragraph came from.

No CMS. No database. No admin panel. git diff is the audit log.

Edit mode: click a paragraph and type

The trick

Every markdown compiler knows where each block lives in the source file, down to the character β€” and then throws that away. We keep it.

  1. A tiny plugin stamps each rendered block with its source range.
  2. Clicking a block makes it editable in place.
  3. On blur, the HTML converts back to markdown and splices into the file at that exact range.

Everything else falls out of that loop. Adding a paragraph? A splice with an empty range. Deleting one? A splice with an empty replacement. The hover toolbar is just those splices with buttons on.

Run it

pnpm install
pnpm dev

Write in content/*.mdx. Every doc gets a card on the home page.

What's inside

✏️ Edit β€” prose is editable in the page: paragraphs, headings, lists, quotes, even text inside components. Bold, links, code, and citations survive the round trip.

πŸŽ™ Narration β€” you're forced to hear your own prose. Hover a section, hit the mic, and a 3-second countdown drops you into a live take with a waveform of your voice β€” then you listen back before keeping it. Silence is trimmed automatically. A small speech model (on your machine, dev only) pins every word to its moment, so playback highlights the word being spoken and skips your pauses. Rewrite a sentence and its audio goes stale until you read it again. Readers get a β–Ά that plays from any section onward.

πŸ”Š Synthetic voice β€” sections you haven't read yet can be filled by a local TTS model (Kokoro-82M, Apache-2.0, ~92 MB), rendered once on your machine from the Voice panel β€” which shows what your hardware can run, and the model's size, engine, and license before anything downloads. Synthetic takes are visibly marked, never count as your reading, and are replaced the moment you record the section yourself. Emoji are spoken sensibly or skipped. The full model landscape we evaluated lives in docs/tts-models.md.

✍ Provenance β€” proof of care, measured. Sessions, days, active time (idle tabs count nothing), edits landed, words moved, and typed-vs-pasted keystrokes β€” pasting a wall of generated prose leaves a visible signature. Stored in git beside the source; ships with every export.

πŸ’¬ Comments β€” feedback at any zoom: a phrase (select it first), a block, a section, or the whole doc. Reactions, grades, and a sidebar listing everything in document order. One click exports it all as JSON β€” with the text each comment targets β€” ready to hand to an agent. Lives in the reader's browser, never in the file.

⧉ Copy as markdown β€” the whole source, one click, straight to your agent's context window.

Plus the quiet stuff: a table of contents with per-section read times, a reading-progress ring, Tufte-style margin notes, footnote citations, and a 🌑 writing-lint mode (parked behind a flag while we rethink it).

Ship it

pnpm export                # one self-contained HTML file
DOC=colophon pnpm export   # any doc by name
AUDIO=1 pnpm export        # narration inlined (topbar dropdown does this too)

Exports carry only that doc β€” other drafts stay out of the bundle. Works from file://. Editing never ships. Pushes to main deploy the whole site to GitHub Pages, narration included.

The rules that keep it sane

WhatLives inBecause
Prosethe pageediting where you read
Structure & propsthe .mdx filestructure belongs in source
Reader feedbackthe reader's browsermarginalia isn't the document
Provenance & audiogit, beside the sourceproof should travel
TOC, read times, heatderived at rendercan never drift from the source

One rule above all: nothing gets a second home. The file is the document; everything else is derived from it or deliberately kept out of it.

Honest limits

Component props aren't inline-editable yet, tables and endnotes are file-edited, rewriting a block orphans its comments and audio (reverting revives them), and feedback is single-reader until the sync server exists. All tracked in ROADMAP.md, along with the gated local-model reading assistant.

Standing on

  • TiddlyWiki β€” proved a document can be its own editor, twenty years ago.
  • MDX + remark β€” whose source positions are the load-bearing fact here.
  • turndown β€” the way back from HTML to markdown.
  • Tufte β€” the margin notes.
  • TinaCMS β€” the productized cousin, and the off-ramp if this ever needs multi-user editing.

Contributors

Languages

JavaScript

77.8%

CSS

13.1%

MDX

7.6%