Notes
A CRUD feature on Cloudflare D1 with form actions, a dynamic route, an error page and a schema-mode TRON endpoint.
#The feature folder
src/lib/norns/notes/:
shared/schema.cdefinescreateNoteSchema(title trimmed and required, optional body),updateNoteSchema, the row shapenoteSchema, andnoteWire, the TRON schema derived from it withtronSchemaFromValibot(noteSchema, { id: 'notes.v1', path: '$.data' }).server/module.cbindsdbtransiently from the request'sevent.platform.env.DB, thennotes.repoandnotes.servicetransiently on top of it (see Cloudflare D1 for the code).server/repo.cis hand-written SQL on the raw D1 API:list,get,create,update,remove, every call async.server/service.cis a thinNotesServicewith typedNoteandNoteInput.server/public.cexportsnotes(container)with the same five operations.
migrations/notes/20260508_001_init.sql creates the table.
#Routes
src/routes/examples/norns/notes/+page.server.c:
export load := page.load
handler: async ({ container }) =>
notes: await notes(container).list()
export actions := page.actions
create:
input: createNoteSchema
run: async ({ input, container }) =>
id := await notes(container).create input
throw redirect 303, `/examples/norns/notes/${id}`+page.n renders the create form with Form, Field, Input, Textarea and Btn, echoing form?.values back into the inputs, and lists notes as Card links.
[id]/+page.server.c loads one note (throwing error 404 when missing) and defines update and delete actions that read event.params.id. [id]/+error.n renders the 404.
#The API endpoint
src/routes/api/notes/+server.c demonstrates schema-preloaded TRON:
export GET := route
serializer: tronSerializer({ schema: noteWire })
handler: async ({ container }) =>
data: await notes(container).list()
export POST := route
input: createNoteSchema
handler: async ({ input, container }) =>
id: await notes(container).create inputBoth ends import the same compiled contract, so no shape declarations travel and the response is tagged #notes.v1. Clients without Accept: application/tron still get JSON.
#The vanilla twin
src/lib/svelte/notes/ (db.ts, repo.ts, service.ts, schema.ts) and src/routes/examples/svelte/notes/ implement the same feature in .svelte / .ts without the runtime, for a side-by-side comparison.