[Guide] Build a Notes App - implementation notes
The Notes guide is pushing a very specific posture: every screen is a route document, sync decisions are render-visible effects, and caches/DOM/vault state are all flexible sources of truth so typing stays fast while routes stay stable.
How do you keep 'DOM truth while typing' and 'vault truth for consistency' from fighting each other? Do you store derived previews/search results in the vault like the guide suggests, or keep them computed to avoid drift? If every screen is a route document, what evidence do you render so you can debug which document wrote what?
Comments (10)
Back to latestThe 'multiple truths' framing is realistic. Notes apps are basically draft truth vs saved truth vs preview truth all at once.
If you try to enforce one truth, typing feels bad or navigation feels brittle.
The guide is consistent with the docs posture: store derived state when it makes the UI 'always ready'.
If previews/results are expensive, compute once and keep them as part of the contract surface.
Related: Core Concepts Best Practices and State Management Best Practices.
The vault mirror idea makes list routes simpler. The list doesn't need to know the whole note, just a stable preview surface.
If the mirror is stable, the list becomes predictable even when edits are happening elsewhere.
Counterpoint: storing derived search results is a risk. If the query changes quickly, you can end up with stale results that look authoritative.
I'd want some marker that says when the results were derived.
Agreed. If we store derived values, we should also store their provenance (query, derivedAt).
Otherwise we traded compute cost for debugging cost.
The 'render-visible effect' idea is underrated. If sync happens, it should be visible somewhere so you can reason about it.
Related: Data Fetching and Caching Best Practices.
The "vault + mirror" split clicked for me because it stops the list from becoming an editor.
List reads previews; editor owns draft truth; vault owns shared truth. Three truths, but named and bounded.
We adopted the provenance suggestion and it helped a lot for debugging derived search:
ts
write('resultsMeta', { query: vault.read('query'), derivedAt: Date.now(), count: results.length });
Then we render data-query + data-derived-at in internal builds so screenshots show what the results *claim* to be.
Counterpoint to storing results: I only like it when the query itself is treated as route truth (or at least vault truth) and rendered as evidence.
Otherwise you can store results for a query that no longer matches what the user is looking at.
Yeah, agreed. The guide's posture is basically: if you're going to store it, store the contract keys around it (query + derivedAt).
That keeps stored derived results from becoming an invisible cache with no explanation.
Small but important: the editor document storing a preview slice is a nice example of derived state used for UX, not performance theater.
If the preview is stable, the list doesn't thrash while you type.
The guide also quietly teaches a migration trick: if every screen is a document, you can move the editor between file routes and component routes without changing the data model.
That reversibility is a bigger win than the specific vault APIs.