Plan
Roadmap for building docs/spec.md; section numbers refer to it. This file holds the order of the work and items that touch several files. Finished work is one line each: the detail lives in the code’s @prose blocks, the tests, git log, and docs/lessons.md.
Done
- 0.1.0 and after — a dev route on Devframe with a Svelte client, the
@noteannotator with safe writes, symbol and staleness checks, the HTML strip, and a released tarball (#2–#14). The parser (comments fromoxc-parser, content-derived anchors,.svelte/YAML/TOML scanners) and the git-aware tree walk carry over; the rest is dropped (spec §6). - Field use and the rewrite — sitez and markz used 0.1.0; the route, notes and checks went unused, the
prose/docs and@prosewere read (lessons.md). The spec is now the convention plus a read-only renderer (#15–#17). - Cut the dropped code — Devframe, the client, the Vite plugin, notes, checks and git blame are gone; the parser keeps blocks, chunks, pending and anchors (
declaredIdentifiersmoved tosrc/names.ts), andsrc/tree.tsis a plain walk withprose/as an ordinary folder. The library exports the parser and the tree untilprose .lands. prose .—src/cli.ts,src/server.ts,src/render.ts,src/highlight.ts,src/style.ts: folder, Markdown, source and JSON pages as server-rendered HTML, weaving ported from the 0.1.0 client, Markdown through markz, shiki on the WASM engine with a content-keyed cache, live reload over server-sent events, default port 1234, Node 26 (markz requires it). The file tree on the left (src/rail.ts), from the walk’s file list alone, as the 0.1.0 client’s rail was. Code shown by default with file line numbers, wrapped with a hanging indent, tabs at two; a remembered Prose & Code / Prose only switch, centred in the bar; a header on every run (chevron, lines, language) that stays when collapsed; code widened to 100 columns beside a prose measure; shiki’s CSS-variables theme in the page’s palette; the rail restored before first paint and held still by a view transition. Speed: parses cached by modification time, the highlighter started with the server, links prerendered on hover, and live reload connected only while a page is visible, since six idle tabs holding one connection each left new pages waiting.@proseinside a class — a JS, TS or CSS block counts at any depth when it starts its own line, so markz’sclass Parserreads method by method (block.ts, 16 blocks where it had one). A block inside a class or function is named by the first member or declaration below it, from the file’s AST (declaredAfterinsrc/names.ts). YAML and TOML keep column 0.prose build— the reader as static files (spec §4.4):renderRouteinserver.tsis the seam the server andsrc/build.tsshare;HEADexported withgit archive; a file’s page at its path plus.html, which a GitHub Pages spike (amitkaps/pages) showed is served at the local URL with no redirect, and a sourceindex.htmlatindex.html.html; the tag and commit in the bar, no live parts, the same bytes per commit; output in.prose/site, a folder it made or none. Cloudflare’s.htmlhandling is untested.prose publish— the build committed to an orphanprosebranch through a temporary index,commit-treeand a conditionalupdate-ref, never checking it out and never pushing (spec §4.5,src/publish.ts);--domainwritesCNAME, carried forward;.nojekyll. This repo publishes toprose.amitkaps.com(DNS on Cloudflare, DNS-only, toamitkaps.github.io), so no site needs a base path yet.- Every file in the walk — every file git lists has a page (spec §4.1, §4.2): dotfiles,
LICENSE, lockfiles, images. Text past 1,000 lines or 100 KB is cut with what’s left said; a binary file gives its type and size, an image shown inline as adata:URL; lockfiles and files over 200 KB aren’t parsed for prose. Ignored files stay out of the rail; locally a folder’s page ends withIgnored here:, which the build leaves out. The walk never follows a symbolic link, so a build can’t publish a file outside the commit. - A 404 page —
prose buildwrites404.htmlwith the file tree, which GitHub Pages and Cloudflare serve for any missing address, and GitHub Pages for all of.github/, which it never publishes (a spike onamitkaps/pages). - 0.2.0 — the README rewritten around the two things, with install, the commands and the §5 snippet; released as a GitHub release tarball, as 0.1.0 was.
docs/— the folder for writing that spans the code isdocs/, notprose/, so “prose” names only the package and the@prosemarker;.gitignorecut to what this repo produces.
Open work, in order
4. Use it
- Look at it in a browser on sitez and markz: typography, folded code, mobile width.
- base, sitez, markz: install 0.2.0, remove
prose()from their Vite configs, replace the snippet inAGENTS.mdwith spec §5, and fold sitez’s open@note(src/site.ts) into its prose. -
prose/→docs/in sitez and markz (spec §3.4), with their links. sitez reads its content folder by name (src/check.ts), so it learnsdocs/. markz’sdocs/is its website (markz.amitkaps.com), not docs: it moves tosite/first (root scripts, workspace, package name, CI paths), thenprose/takesdocs/and the site reads its pages from there. - markz: make
@proseblocks link togrammar.mdinstead of restating its rules (spec §3.5). - Two weeks of work on sitez and markz, then decide whether the renderer stays (spec §7).
Later
-
@prosein.gitignore: its#comments are what the YAML and TOML scanner reads, so it’s a mapping by file name and a row in spec §3.1. Python, shell,DockerfileandMakefileuse the same comment, when a repo has them. - Publish to npm once the CLI has settled; check whether an unscoped name is available for
npx.
Open questions
See spec §8.