Recipe: Journal
A Collection for the entries plus a Document for preferences. Key entries by a sortable id so listing is naturally chronological. Assume the singleton app store and light-DOM routes around this.
// www/store/app.ts
type Entry = { title: string; body: string; date: string /* ISO */ }
type Prefs = { defaultMood: string }
const store = new Store(backend, {
documents: ['prefs'],
collections: ['entries'],
versions: [/* … */],
})
export class App {
prefs = store.document<Prefs>('prefs', { defaultMood: 'neutral' })
entries = store.collection<Entry>('entries')
// …preload both in #init…
write(title: string, body: string) {
// date-prefixed id → list() returns entries in date order
const id = `${new Date().toISOString()}_${crypto.randomUUID().slice(0, 8)}`
return this.entries.set(id, { title, body, date: new Date().toISOString() })
}
async recent(limit = 20) {
const ids = (await this.entries.list()).sort().reverse().slice(0, limit)
const all = this.entries.value ?? new Map()
return ids.map((id) => ({ id, entry: all.get(id)! }))
}
}
The pattern generalizes to any “log of things over time” app — workouts, expenses, reading notes. Use getHistory(id) if you want to show how a single entry was edited over time (the CRDT keeps it).
Next: Gallery swaps JSON entries for binary images with @civility/blobs.