Every decision that shaped the app, with the reasoning kept next to it.
Each record states the situation, the decision taken, and what it costs. Superseded records stay published and point at their replacement.
01records
Newest first.
ADR-0058
A folder's board can be embedded in a note
ADR-0057 made database views a route and rejected an embedded block, because a React grid inside ProseMirror would pull cross-note projections into the editing…
ADR-0057
Database views are a route over note properties
Notes carry typed properties (note properties), but the only place to read or change them was one note's metadata panel.
ADR-0056
Account deletion purges cloud data before local reset
Account & sync offers a guarded account deletion action. The authenticated Worker records a deletion tombstone before purging the account's sync Durable…
ADR-0055
Workspace module boundaries
apps/workspace/src holds 23 feature folders next to shell, commands, store, bridge (now platform), contracts, and shared.
ADR-0054
Recurring tasks repeat in the document
ADR-0053 put a task's due date on its checklist line so Markdown, exports and other editors keep it.
ADR-0053
Task due dates live in the checklist line
WorkspaceTask has carried a dueDate since ADR-0031, but nothing set it. A date that only exists in SQLite would disappear from the note's Markdown, so an…
ADR-0053
Math blocks and the dollar trigger
Notes need inline and display math. The portable Markdown spelling that Obsidian, GitHub, Pandoc, and most static site generators read is $...$ for inline math…
ADR-0052
Public note links
Users want to send a note to someone who does not use Skriuw: a read-only page on skriuw.com behind a link.
ADR-0051
Remote images download once at import, with consent
ADR-0023 keeps remote images in imported Markdown as blocked placeholders so that opening a note can never fetch from the network.
ADR-0050
oxfmt and oxlint gate the v2 TypeScript
The v2 gate checked Rust with cargo fmt and cargo clippy -D warnings, but TypeScript only with tsc.
ADR-0049
Group the v2 repository by product boundary
The v2 product had accumulated top-level application, service, and shared TypeScript directories.
ADR-0049
One shared icon system, Fluent Regular, motion as data
Icons were drawn three different ways. The desktop hand-copied about 120 Lucide drawings into apps/workspace/src/shared/icons/static.tsx and normalised their…
ADR-0048
A native mobile shell over the shared Rust core
Skriuw reaches phones today as the installed browser build: the compact shell (ADR-0041, ADR-0047) over worker-owned SQLite WASM and OPFS (ADR-0027).
ADR-0047
The compact shell owns the back gesture and the install offer
ADR-0040 made the browser build installable and ADR-0041 gave it a phone layout. Installed on Android, three platform behaviours still read as a website:
ADR-0046
Per-account local workspaces
A cloud workspace id is derived from the account: sha256("skriuw-sync-workspace-v1\0" + userId), computed in apps/sync/src/provision.ts.
ADR-0045
Rendered Mermaid fences
The editable diagram block (spec) covers one Mermaid family: flowcharts its own parser accepts.
ADR-0044
Locked notes
Users asked to put a PIN or passcode on a single note or a whole folder. Two very different features answer that request.
ADR-0043
End-to-end encrypted sync
ADR-0026 replicates versioned domain operations through an ordered per-workspace log in a Cloudflare Worker and Durable Object, with large bodies and media…
ADR-0042
Modal Vim editing
Writers who live in Vim asked for modal editing in both editors. ProseMirror has no Vim mode and the community packages cover a handful of motions at most,…
ADR-0041
Full-text content search over a rebuildable FTS5 projection
Workspace search matched note titles from hydrated renderer state. Note bodies were indexed into an FTS5 virtual table, but the table stored raw Markdown, its…
ADR-0041
Cover gradients are named, not styled
v1 let a note wear a built-in theme gradient as well as an uploaded image. v2 shipped only image covers, so a note that wanted colour at the top had to carry a…
ADR-0041
The compact shell is one column with sheets, a tab bar, and touch-owned gestures
The workspace shell is a four-track grid: rail, tree, editor, inspector. On a phone the first three already exceed the viewport and the inspector renders off…
ADR-0040
The browser build is an installable shell that never caches workspace data
The browser build is deployed under /app/ and is the only way to run Skriuw on a phone.
ADR-0040
An AI run is visible work, steered from the note
ADR-0036 moved a text result out of a modal and into the note. Three things it left alone turned out to be the rest of the same problem.
ADR-0039
Provider-agnostic voice transcription seam
Voice dictation turns a microphone recording into Markdown the writer can insert. Speech-to-text differs from the completion seam in ADR-0033 in shape, not in…
ADR-0038
Personal template and saved-search preferences
Personal note templates reference ordinary canonical notes. The workspace settings extension noteTemplateIds records at most 200 source IDs; it never…
ADR-0037
Automatic sync convergence
ADR-0026 replicates versioned domain operations through an ordered per-workspace log and applies them through the same validation as local operations.
ADR-0036
AI text results are reviewed in place, not in a modal
An editor AI action produced a result the writer reviewed in a modal dialog: the proposed text in a scrolling box, an accept and a discard button, and the note…
ADR-0035
The note annotation layer is versioned document data
Skriuw v2 needs freehand annotation over a whole note — ink and simple shapes drawn across the text, including the margins outside the writing column, staying…
ADR-0034
Annotation anchors are document data, conversations are not
A comment thread has two halves that want different homes. The anchor — which text is being commented on — only means anything relative to the document, and…
ADR-0033
Provider-agnostic AI completion seam
AI features need one completion path before local or remote providers, settings, or editor actions are added.
ADR-0032
Task-shaped typing is explicit intent
ADR 0031 forbids implicit promotion so imported Markdown and ordinary checklists cannot silently fill the workspace task index.
ADR-0031
Explicit task promotion
The editor already preserves taskId and blockId attributes on checkitem nodes through JSON, DOM, Markdown, and history, but nothing durable stood behind them.
ADR-0030
Remote cover download
Covers could only come from a local file or an asset already in the workspace. A user holding an image address had to download it by hand and then upload it.
ADR-0029
Stored video media
The workspace blob store, AttachImage operations, and the media library were built exclusively for images (PNG, JPEG, GIF, WebP).
ADR-0028
Browser sync runs the native coordinator logic inside the storage worker
The browser runtime (ADR-0027) is local-only: the OPFS-backed SQLite worker has no sync, checkpoint, or hydration path, while the desktop coordinator…
ADR-0027
Browser SQLite uses a worker-owned OPFS SAH pool
The browser runtime needs the same canonical SQLite behavior as desktop while keeping database, migration, and filesystem work off the renderer thread.
ADR-0026
Optional cloud operation replication
Skriuw v2 must support an independent browser product and optional multi-device synchronization without making the existing desktop application…
ADR-0025
Embedded diagrams use a structured local model
Skriuw needs diagrams that can be created from readable syntax and edited by pointer or keyboard inside a note.
ADR-0024
Previewed and atomic provider import
Provider exports contain more than Markdown. They may carry folders, timestamps, tags, typed properties, local assets, provider-specific links, and unsupported…
ADR-0023
Lossless and reference-safe Markdown transfer
Markdown is both a portable interchange format and the readable projection stored beside each structured document.
ADR-0022
Import into the Skriuw monorepo as the v2 linesuperseded
This codebase started life as remcostoeten/skriuw-standalone: a ground-up rebuild of Skriuw, re-architected for performance from the first commit.
ADR-0021
Tabs and split view
The product ships with one active note and one persistent ProseMirror editor host by deliberate decision (ADR-0020): "one persistent direct ProseMirror view"…
ADR-0020
UI architecture selection
ADR-0004 deferred every UI and editor decision until measured evidence existed. The UI architecture gate in TODO.md required benchmarking editor candidates,…
ADR-0019
Archive compatibility fixtures
WorkspaceArchive is the canonical interchange contract between desktop, recovery flows, and the future web runtime (ADR-0007).
ADR-0018
Read-only Git history integrity and cache rebuild
Git history is an asynchronous projection of SQLite document revisions. Cached history headers can be rebuilt, but rebuilding from malformed Git state could…
ADR-0017
Verified live database swap
Verified restore intentionally creates a new database path. Replacing the canonical desktop database requires coordination with the serialized runtime:…
ADR-0016
Deterministic operation-sequence scale fixtures
The performance contract requires 1,000-note and 5,000-note workspaces before any UI benchmark can run, and the future web runtime must replay the same…
ADR-0015
Scheduled backup rotation
ADR-0008 defines how to create and verify one native SQLite backup, but it does not define when periodic recovery points are due, how many survive, how they…
ADR-0014
Bounded failure diagnostics
Runtime, storage, history, backup, recovery, and integrity failures currently surface through unrelated error enums and broad backend strings.
ADR-0013
Versioned settings and note metadata
Settings were untyped SetSetting key/value rows in appstate. Nothing defined which settings exist, their defaults, their compatibility across versions, or…
ADR-0012
Lossless save batching
Every submitted document save currently opens and commits an independent SQLite transaction.
ADR-0011
Graceful storage runtime shutdown
WorkspaceRuntime spawned a detached storage worker with no lifecycle contract. Nothing rejected new work during teardown, nothing guaranteed accepted requests…
ADR-0010
Backend-owned node ranking
Tree callers currently submit durable raw integer ranks. That leaks storage mechanics into UI code, permits accidental ties, and provides no recovery when…
ADR-0009
Subtree trash and permanent purge
A tree operation on a folder affects the user's view of its complete subtree. Marking only the selected row as deleted without defining inherited availability…
ADR-0008
Verified native SQLite backups
The desktop database uses WAL mode. Copying only the main database file can omit committed WAL content or produce an inconsistent recovery artifact.
ADR-0007
Portable workspace archive
Users need export, import, recovery, and migration between desktop and a future web runtime.
ADR-0006
Native Git history materializer
Desktop history needs durable Markdown diffs without requiring users to install Git and without introducing filesystem or native-library dependencies into…
ADR-0005
Asynchronous Git history
Users need note history. Git offers durable Markdown diffs but filesystem writes and repository operations cannot enter editing or navigation paths.
ADR-0004
Defer UI and editor selection
Framework popularity and bundle size do not prove post-startup latency. Editor DOM work is expected to dominate note switching and typing.
ADR-0003
Operation protocol and runtime adapters
Desktop uses native SQLite. Future web may use SQLite WASM. UI behavior must not import Tauri or database details.
ADR-0002
SQLite is canonical
Markdown files are portable but make rich-editor round trips, tree metadata, atomic multi-record writes, search indexing, and crash recovery more complex.
ADR-0001
Standalone local-first product
Desktop ships first. Notes must remain usable without accounts, server availability, or network connectivity. A later web runtime may exist.
The decisions are public. So is the app.
Open the browser build and see what these records add up to. Nothing to install, no account.