Skip to content

Core concepts

Three decisions run through the whole of Louise. Internalise them and the API surface stops surprising you.

Louise assumes a V8 isolate (workerd / Cloudflare Workers), not Node. It never imports node:*, never assumes a filesystem, and expects Web-standard globals (fetch, crypto.subtle, Request/Response). The commerce clients talk to Stripe, Square, and Fourthwall with raw fetch and HMAC-verify webhooks with crypto.subtle rather than pulling an SDK that assumes Node.

The one deliberately non-standard touch is Error.captureStackTrace in errors — a real V8 engine feature that Louise feature-detects (if (Error.captureStackTrace)) so it degrades cleanly anywhere.

On Workers, bindings and secrets only exist at request time. So Louise takes them as arguments:

db(env.DB); // not: db() that reaches for a global
enqueue(env.MY_QUEUE, msg); // not: enqueue(msg)
sendEmail(env.EMAIL, input);

This keeps every primitive:

  • Framework-agnostic — Astro, Hono, or a bare Worker all call the same functions.
  • Testable — pass a fake Queue/EmailSender/D1 and assert, no runtime mocking. (See the package’s own test/ suite.)
  • Schema-neutraldb() hands you a Drizzle instance over your schema. Louise ships exactly one opinionated table, site_settings, and it’s opt-in.

The rich-text editor serializes to HTML, and the site stores and renders that HTML directly (set:html). No ProseMirror ever runs on the Worker; on load the editor re-parses the stored HTML.

The trade Louise makes is deliberate: HTML is trivially renderable server-side with zero client JS, at the cost of needing a parser-based sanitizer on the write path. Louise treats the sanitizer as the security boundary — a strict per-tag attribute allowlist, href/src/style scrubbed — because stored HTML is rendered verbatim.

Editing is gated by edit mode, which a host app resolves per request (typically a sticky cookie toggled by a query param) and exposes to templates. Two facts matter:

  • The page’s edit mode controls whether edit affordances render.
  • A separate, session-derived signal (e.g. locals.editor) controls whether writes are trusted. Never authorize a save on the page’s edit mode alone.

Louise gives you the client and the field contract; you own the auth. The Auth & edit mode guide walks the reference implementation (Better Auth magic-link + passkeys), but any auth that can answer “is this request an editor?” works.