Interactive books are a determined application over vaults and the native APIs
State: open/accepted
Summary
Section titled “Summary”- The four augmented book apps and their four content formats are
replaced by one set of projects inside
solutions/determined/, with three deployables: the books product, an authoring CLI, and a static print site. - A book is an Obsidian vault. The reader, authoring and progress all run over determined’s native vault APIs and the frame. Books has no backend of its own, and it adds platform code only where a gap is generic.
- Exercises are fenced blocks,
vim-exerciseandsql-exercise, rendered by a markdown plugin into runners that are plain Vue. The same runners mount as islands in the print site. - Learner state is notes in a learner vault, keyed by book id, with a
learner_idon every note from the start.
Status
Section titled “Status”Accepted. Sequenced by M-8L1Z. Supersedes the relocation plan in M-E1EU, which moved the four apps intact and kept every format; its six tasks are closed as superseded. B-0JM1-books-format-convergence is resolved by this decision: the vault is the one model.
Context
Section titled “Context”The augmented family, adopted from sksizer/augmented_books in July
and August 2026, carries four apps for one idea: vimit (Tauri and
Astro, the vim curriculum), vimit_prototype (Nuxt, editor
experiments), augmented-books (Tauri and Vue, a desktop reader with
WASM SQLite runners) and learn_web (Nuxt, a web reader and editor).
They hold four content formats: Astro collections, a JSON tree with
referenced files, a +book.md hierarchy, and a Rust dialect of the
hierarchy that misparses the others. The desktop app finds its content
through an untracked symlink. Three of the four render markdown with
their own stack.
Meanwhile the repo grew the pieces these apps reimplement. The frame
and its module registry. markdown-ui over obsidian-md and
obsidian-editor, with a plugin seam that routes a fence language to a
component. code-editor with an extensions prop. The platform’s
generic vault surface: read, write, create, rename with link
rewriting, frontmatter writes under etag CAS, backlinks, search, the
graph, a paged tree, and the roster. obsidian-astro for vault to
static site. Fitness shows an experience with its own state over the
frame alone, and agent-pants shows a solution mounted as an experience.
The owner’s targets are three: a desktop and hosted reader that records progress, downloadable books, and a printed static version. Authoring is a deployable of its own. Runners must cover vim and SQLite now and other kinds later.
Decision
Section titled “Decision”-
A determined application, not a solution. Books runs determined’s
platform-serverand reads the vault API through@determined/vault-platform-client, which is a build artifact ofcrates/determined-platform— the platform crate’sbuild.rsemits it. A consumer of a generated client cannot sit outside the solution that generates it, and books has no backend of its own to justify a solution under D-0001. So it lives insidesolutions/determined/, beside the other applications on the same framework.Project Path What it is @determined/book-modelsolutions/determined/packages/book-model/Note kinds, exercise specs, contract corpus @determined/runnerssolutions/determined/packages/runners/Vim and sqlite runners, plain Vue @determined/exp-learningsolutions/determined/experiences/learning/The reader, author mode product-bookssolutions/determined/products/books/Thin product: frame, experience, ui Book vaults solutions/determined/vaults/<book>/One vault per book The authoring CLI and the Astro print template are later phases and take determined’s usual homes:
solutions/determined/apps/andsites/. -
No backend of its own. The experience uses
@determined/vault-platform-client’s generated transport and the frame. It declares no server route and no ontogen schema, and the product extends no shell. A platform addition is allowed only when it is generic and named here. -
Vault per book. A book is a folder that is a vault:
book.mdwith the stable id, parts and modules as notes, glossary and card sets inside the book. Download is import into the roster. Search, backlinks and the graph come from the platform per vault. -
Exercises as fences.
vim-exerciseandsql-exercisefences with a YAML body validated bybook-model. One markdown plugin mapslang:<fence>to a runner. Runners take a spec and emit attempts; they depend on neither Nuxt nor the transport. SQLite runs on sql.js in the browser; the wasmtime sandbox is retired. -
Learner state as notes. A learner vault holds, per book, a progress note, a card-state note and an append-only attempts note. Keys are the book id, never the roster’s vault id. Every note carries
learner_id. -
Print via Astro.
obsidian-astrogains a fence-to-component hook; the print site mounts the runners as islands. Progress is out of the static site. -
Promotions.
@determined/code-editorand@sksizer/obsidian-astromove topackages/ts/, names unchanged: both are framework-general and depend on nothing in determined.@determined/vault-platform-clientdoes not move. It is generated fromcrates/determined-platform, so it belongs beside the crate that writes it.
Platform gaps the experiment names
Section titled “Platform gaps the experiment names”| Gap | Ruling |
|---|---|
| Import a vault from an archive | Generic. Added to determined-platform in P5 |
| Identity for a hosted instance | Deferred. Personal instance behind the platform token; learner_id on every note keeps it an auth change |
| A doc read with its embeds inlined | Deferred. P5 measures page loads over HTTP and decides |
| The suite-wide vault roster showing book vaults in the family workbench | Open. Settled in P1 |
Consequences
Section titled “Consequences”- The ontogen crate a fitness-shaped app would carry does not exist. Aggregation over learner state is client-side over one note per book, which is adequate for a review scheduler and would not be for a fitness log.
- The static site and the reader share runners but not chrome. A static Nuxt build of the reader over a static transport is a possible later spike, not this decision.
solutions/augmented/is deleted in the last phase.augmented_webandaugmented_dot_commove tosites/as the superseded plan already specified.- Books shares determined’s dev-port band and its Tauri deep-link
scheme,
determined://, because it is one of determined’s products.
Alternatives considered
Section titled “Alternatives considered”- Relocate the four apps into
solutions/augmented_learning/(M-E1EU). Kept four formats and three render stacks. Rejected. - A fitness-shaped app with an ontogen schema and a domain crate. Proven path, but it adds core code for every learning entity and forgoes the plugin experiment. Rejected for now; the schema can be added later if learner state outgrows notes.
- A separate
solutions/learning/. Wanted by the three deployables, but the reader consumes a client generated by a determined crate, which would make the boundary a fiction on the first build. Rejected. - An app under
solutions/determined/apps/learning/. Correct for a headless tool; wrong for a Nuxt reader that mounts the frame. - Exercises as embedded notes,
drill. Reusable across books and printable as prose, but needs a resolver rule per kind. Fences first; embeds if reuse shows up.