Supabase and R2 stripped out; JSON file and local filesystem take their place

mikeOnBreeze forked Mike to run entirely on a laptop without any cloud dependencies. One commit removes Supabase Postgres, Supabase Auth, and Cloudflare R2, replacing them with a hand-rolled JSON store and direct filesystem reads/writes. The author is a personal injury lawyer who doesn't want client materials leaving their machine.

infrastructuresecurity

The diff is +1888/-3083 across 30 files. @supabase/supabase-js, @aws-sdk/client-s3, and @aws-sdk/s3-request-presigner are gone from package.json. In their place: backend/src/lib/localDb.ts (803 lines of JSON-file persistence) and backend/src/lib/storage.ts (fs/promises reads/writes under backend/data/storage/). The Supabase and auth shims are rewritten as thin wrappers so frontend components didn't need to be touched - frontend/src/lib/supabase.ts still exports a Supabase-shaped client, just one that talks to the local backend.

Auth is effectively a bearer token of the form local-user:<email> accepted as a single fixed user. No session management, no user table lookups. Signed download URLs are generated but don't expire. The JSON store has no locking, so concurrent writes would corrupt state. All of that is intentional for a single-user desktop install.

Two things from this diff are worth noting if you want to port any piece of it. The resolveStoragePath function in storage.ts has an explicit path-traversal check that verifies the resolved path is under the configured root before any file operation. The buildContentDisposition helper on the download route handles filename encoding correctly. Both are defensive details that often get dropped in quick ports.

The upstream Supabase schema is kept at backend/migrations/000_one_shot_schema.sql as reference-only. Nothing runs against it.

So what Skip for any multi-user or production context. The auth model, non-expiring URLs, and absence of concurrency control make it unsafe outside a single-user laptop. Worth a look only if you want the `resolveStoragePath` traversal guard or the `buildContentDisposition` logic, or if you're building a no-cloud dev mode and want a reference for how to shim the Supabase interface without touching every call site.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from mikeOnBreeze/mike-oss, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
24d6a86c Localize storage: replace Supabase + Cloudflare R2 with local filesystem mikeOnBreeze 2026-05-04 ↗ GitHub
commit body
Swaps cloud dependencies for local equivalents so the app runs entirely
on a single machine - JSON file for state, local filesystem for document
bytes, single default user. Original Supabase schema kept under
backend/migrations for reference.

Motivation: working with materials (e.g. legal documents) that
shouldn't be pushed to third-party cloud storage during local
experimentation. For multi-user / production deployments, use the
upstream repo at github.com/willchen96/mike.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-149.md from inside the repo you want the changes in.

⬇ Download capture-thread-149.md