The top of the documentation tree. Structure:
roadmap (this file)
└── milestones/ big outcomes
└── features/ shippable capabilities within a milestone
└── phases/ concrete, ordered steps of work
How to read: start here → open a milestone's README.md → open a feature's
README.md → open a phase file for the actual steps. Background research and rationale
live in ../RESEARCH.md.
Guides: reusable runbooks in guides/ —
NeoVim Rust / Dioxus Project Setup
(portable to any Rust/Dioxus project).
A cross-platform EPUB reader written in Rust with Dioxus 0.7 and developed in NeoVim. Two goals: learn Rust + Dioxus and idiomatic patterns, and build a reader extensible with features missing from existing apps. Desktop first, then mobile and web — one codebase across all targets.
Pivoted from Swift. Earlier milestones were planned for Swift/Readium; the project restarted on Dioxus/Rust. See
../RESEARCH.md§1.
How we build it: thin, end-to-end vertical slices — each step is something a real
reader can use (open a book, see text, turn a page, resume). The MVP slice sequence and the
"learning rides inside the slices" principle are in
vision-mvp-reader.md; the decision is
ADR-0001. Domain vocabulary:
glossary.md. Decisions: adr/.
✅ done · 🚧 in progress · ⬜ planned · ⏸ deferred
| # | Milestone | Outcome | Status |
|---|---|---|---|
| 1 | Foundation | Rust/Dioxus NeoVim toolchain + a buildable desktop app | ⬜ |
| 2 | Basic EPUB Reader | Open an .epub and read it with paging + saved position |
✅ |
| 3 | Reader Enhancements | The features missing from other readers | 🚧 |
| 4 | Multi-platform | Mobile (iOS/Android) + web (WASM) from the same codebase | 🚧 |
| 5 | Sync | Reading position and library converge across devices — with no server | ⬜ |
| 6 | AI Chat | Select a passage, ask an AI about it — Gemini Flash-Lite first, provider-swappable | 🚧 |
Current phase: Phase 18 — API key storage + settings row (opened 2026-09-13). Phase 17 closed 2026-09-13 with the ChatProvider boundary, a Gemini implementation and a live test green (2b9e826, 149 tests).
Phase 9 is done: the
reader builds, launches, imports, pages by swipe and fits the notch on an iPhone and an
iPad, and on real hardware. Android has no phase yet, and web (WASM) stays ⏸. Milestone 3's
candidates — full-text search, annotations, and the bookmarks that
Phase 8 deferred out — are
still unclaimed on its board, and
Milestone 5 — Sync is designed and queued, and
Milestone 6 — AI Chat was captured on 2026-09-11 with six
phases (17–22) but no ADR yet.
TODO.md holds the smaller unscheduled items.
Milestone 5 — Sync is designed and queued. A grilling session on 2026-08-29 turned
"build a backend app with login and cross-device sync" inside out. Drive offers no
optimistic concurrency — files.update has no If-Match — so one shared state file would
silently clobber itself, and arbitrating that is precisely what a server would be for. But
arbitration is only needed when two writers share a file: give every device its own file
and conflicts become structurally impossible, the server has nothing left to do, and what
remains is a pure merge function that tests offline. "Log in to an account" survives as
connect your Google account. Decisions:
ADR-0005 and
ADR-0006, which together supersede
ADR-0004 — the libSQL/Turso path
is dropped, and the local store moves to sqlx. Six phases, starting with a store migration
and ending with book-file mirroring; the merge engine sits third, deliberately ahead of auth,
because it needs no network.
Phase 8 — ToC & Navigation
closed 2026-08-18 and was the last one worked: the reader names the chapter you are in
and opens a contents panel, scrolled to where you are, whose every row jumps. The phase was
never really about parsing — rbook hands over the tree — but about ToC and spine being a
many-to-many mapping (see glossary.md), which the bundled fixture makes
concrete at 15 spine items against 18 entries. "Which chapter am I in?" got a chosen answer
and a defence, not an array lookup. 117 tests green.
Phase 4 — Themes & Typography closed before it: six settings (theme, font size, line height, page margins, max line length, font family) layer over the publisher's CSS without replacing it, persist across restarts, and re-anchor the reading position after every reflow. 108 tests green.
The July 2026 review backlog is now empty — R6 (case-insensitive matching, the "Page 1 of 0" label) landed as a sitting inside Phase 4, and R3 (a real error type) went into Phase 7 as Step 6a.
Milestone 1's board is stale. It reads ⬜ while the toolchain it describes has plainly been in daily use for three milestones. Its phases need reconciling against reality — the one criterion that may genuinely be unmet is debugging from NeoVim (
:RustLsp debuggables).