React Forum
Blog & Guide Responses
Jan 03, 2023 · 04:00 PM

[Guide] Build a Notes App - implementation notes

Started by Camille Duarte
guidenotesvaultroute documentsdraft truthderived state

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.

Read the guide

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 latest
Maya Henson
Jan 03, 2023 · 04:06 PM

The '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.

Dmitri Kline
Jan 03, 2023 · 04:14 PM

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.

Salma Qureshi
Jan 03, 2023 · 04:22 PM

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.

Keira Santos
Jan 03, 2023 · 04:33 PM

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.

Camille Duarte
Jan 03, 2023 · 04:39 PM

Agreed. If we store derived values, we should also store their provenance (query, derivedAt).

Otherwise we traded compute cost for debugging cost.

Priya Liao
Jan 03, 2023 · 04:52 PM

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.

Hana Saito
Jan 03, 2023 · 05:04 PM

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.

Rowan Pierce
Jan 03, 2023 · 05:18 PM

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.

Avery Chen
Jan 03, 2023 · 05:31 PM

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.

Camille Duarte
Jan 03, 2023 · 05:36 PM

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.

Inez Park
Jan 03, 2023 · 05:49 PM

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.

Benji Rios
Jan 03, 2023 · 06:02 PM

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.