Search the site
Find pages, services and blog posts
Skip to content

Case Studies

Recent work on client SvelteKit platforms and my own projects. Client work is anonymised; the rest links to the code or a write-up.

Guardrails for agent-written SvelteKit code

Client work: a large SvelteKit monorepo

SvelteKitSvelte 5TypeScriptCoding agents
Problem
Most of the code on a client platform was being written with coding agents, and more developers were about to join. Once an agent copies a shortcut, the next session treats it as the way the app works.
What I did
Put the rules in code rather than in agent instructions: a boundary checker that parses the source, a lint plugin that wants a comment justifying every $effect, a route data audit and a module ownership check. All of them run in pnpm check before a deploy.
Outcome
  • The custom checks stopped 8 of 38 failed UAT deploys, and nobody switched one off to get a deploy through
  • Exceptions down from 43 to 16, which the team later took to 12
  • The checks went with the code at handover and still gate UAT and production deploys

Permissions, auth and deploys for a multi-tenant app

Client work: a multi-tenant workflow platform

SvelteKitPostgreSQLBetter AuthAWS ECS
Problem
Several organisations share one SvelteKit app, each with its own teams and roles, and none may ever see another's data. Role checks scattered through route files stopped holding up, and every deploy dropped requests for a few seconds.
What I did
Moved authorisation into one attribute-based engine whose rules compile to parameterised SQL, so out-of-scope rows never leave Postgres. Replaced Auth.js with Better Auth on the same pg Pool as the raw SQL data layer, and fixed the ECS settings so the old container serves until the new one is healthy.
Outcome
  • Rows a user may not see return 404, with a cross-tenant end-to-end test for each resource
  • No ORM engine or generate step left in the Docker image
  • Rolling deploys that keep the old container serving, with automatic rollback

A Svelte UI for AI document extraction

Client work: an AI document extraction platform

SvelteKitSvelte 5PostgreSQLVitest
Problem
Extraction runs take far longer than a web request should, several people can have the same record open, and every value the model pulls out has to be checked by a person.
What I did
The SvelteKit app uploads, stores and queues, and a separate worker runs the extraction and writes each step back to Postgres. The UI reads that saved state, every action goes through a permission-checked server function, and reviewers leave feedback in categories rather than a thumbs down.
Outcome
  • A refresh, a dropped connection or a second viewer all see the same state
  • The agent's tools go through the same permission rules as the UI
  • Feedback categories that can be counted and turned into evals

Two production sites on SvelteKit 3

svelteconsulting.dev and oestechnology.co.uk

SvelteKit 3Vite+TypeScriptNode 24
Problem
Clients keep asking whether they should move to SvelteKit 3. This site was still on Kit 2.49, Vite 7 and node 22, and I wanted to know what breaks before I told anyone to upgrade.
What I did
Moved oestechnology.co.uk first and this site the day after, from a written checklist: $lib to #lib package imports, env vars through $app/env, the Kit config folded into vite.config.ts, and ESLint and Prettier replaced by Vite+.
Outcome
  • Both sites live on SvelteKit 3, adapter-node 6 and node 24
  • Remote functions and async Svelte in production on this site
  • What broke is written up, from a missing PROTOCOL_HEADER to a Playwright teardown that hung

my-pi, my own coding-agent harness

Open source, since April 2026

TypeScriptPi SDKMCPLSPSQLite
Problem
Off-the-shelf coding agents didn't give me the controls I wanted on real codebases: secret redaction, LSP diagnostics, session recall, and a way to stop agents writing Svelte I'd only have to rewrite.
What I did
Built my own distribution on the Pi SDK as a monorepo of packages that also install on their own. One of them, pi-svelte-guardrails, blocks $effect in agent writes to .svelte files and points the model at $derived, event handlers or actions instead.
Outcome
  • 1,457 commits and 31 packages since April 2026
  • 131 GitHub stars and 1,655 npm downloads of my-pi in the month to 26 September 2026
  • The harness I use every day, including on client codebases

First-party analytics with node:sqlite

scottspence.com and the sites around it

SvelteKitnode:sqliteNode 24
Problem
I wanted page view numbers I own, with no cookies. The first version used better-sqlite3, and a routine upgrade of its native module broke the production build.
What I did
A SvelteKit server hook records each view after the page renders, identifies visitors with a salted hash that changes every day, and writes to SQLite through an in-memory queue. In August 2026 I swapped better-sqlite3 for node:sqlite, which ships with Node 24.
Outcome
  • Running on scottspence.com since December 2025, and now on svelteconsulting.dev and oestechnology.co.uk
  • No cookies, no client script and no new dependencies
  • No native module to build on deploy

Tracking down 1.3 billion row reads

Turso database on scottspence.com

SvelteKitTursoSQLite
Problem
My site showed 1.27 billion database row reads from about 742,000 queries, far more than the traffic explained.
What I did
Traced it to a popular posts query doing three full table scans with no index. Replaced the three CTEs with one window function query and added an index on the filter and sort columns.
Outcome
  • Around 95% fewer row reads per execution, on paper
  • Sub-second responses for the popular posts query

Have a similar problem?

Tell me what you're seeing and I'll tell you how I'd approach it.

Get in Touch