juanjo makes Mike runnable on a laptop, no cloud account required

The second leg of juanjo's self-hosting push swaps a cloud file-storage dependency for something that runs entirely on the developer's own machine.

infrastructureintegration

Mike normally leans on Cloudflare R2 - a cloud service for storing files like uploaded documents. That's fine in production, but it means anyone who wants to spin up Mike locally needs a cloud account and credentials before they can even see the thing run. juanjo's fork drops in MinIO, a self-hosted stand-in that speaks the same protocol as R2, so the whole stack now starts with a single command and no external sign-ups.

The change is deliberately minimal and reversible: production deployments on R2 are untouched unless you opt in. juanjo also cleaned out a handful of unused packages on the way through and documented the tradeoffs, including one piece of naming debt they chose to defer rather than paper over.

So what For any team evaluating Mike or building on top of it, this is the difference between a half-hour tire-kick and a weekend of cloud setup before you've seen a single screen.

View this fork on GitHub →

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

Commits in this thread

12 commits from juanjo/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
f576fca1 docs: spec for MinIO local S3-compatible storage Juan Vidal 2026-05-08 ↗ GitHub
Add MinIO + bucket-init sidecar to docker-compose; make storage.ts
provider-agnostic via R2_REGION and R2_FORCE_PATH_STYLE; delete the
unused frontend storage duplicate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c5d06a24 docs: implementation plan for MinIO local storage Juan Vidal 2026-05-08 ↗ GitHub
Six tasks: compose changes, env defaults, storage.ts provider-agnostic
client, delete unused frontend duplicate, README docs, manual smoke
test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ef16e3a6 feat(compose): add MinIO and bucket-init for local S3 storage Juan Vidal 2026-05-08 ↗ GitHub
commit body
Adds a minio service (S3 API on :9000, console on :9001) and a
one-shot minio/mc sidecar that creates the 'mike' bucket on first
compose-up. Persistence via mike_minio_data named volume.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cf2effd2 chore(compose): parameterize minio credentials, document init exit-0 Juan Vidal 2026-05-08 ↗ GitHub
commit body
Use ${MINIO_ROOT_USER:-minioadmin} / ${MINIO_ROOT_PASSWORD:-minioadmin}
in both the minio env block and the minio-init entrypoint, matching
the postgres service convention. Adds a comment so contributors don't
mistake minio-init's Exited (0) for an error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
720353fb chore(env): default R2_* vars to local MinIO Juan Vidal 2026-05-08 ↗ GitHub
commit body
Updates root and backend .env.example with MinIO endpoint and dev
credentials, plus the new R2_REGION and R2_FORCE_PATH_STYLE knobs.
Prod R2 config is unaffected - both new vars default to R2-friendly
values when unset in the storage client.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ea0707d6 feat(storage): make S3 client region and path-style env-driven Juan Vidal 2026-05-08 ↗ GitHub
commit body
R2_REGION (default 'auto') and R2_FORCE_PATH_STYLE (default false)
preserve current R2 prod behavior when unset, and let MinIO drop in
for local dev (region 'us-east-1', forcePathStyle true).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2a1cc6ff chore(frontend): remove unused storage.ts duplicate Juan Vidal 2026-05-08 ↗ GitHub
commit body
frontend/src/lib/storage.ts had zero importers - a leftover copy of
the backend module. Storage credentials only ever live on the server;
the frontend gets a signed URL from the backend and never holds keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8c2a0737 docs(readme): document local MinIO setup Juan Vidal 2026-05-08 ↗ GitHub
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aad90dab chore(frontend): drop unused AWS SDK dependencies Juan Vidal 2026-05-08 ↗ GitHub
commit body
The frontend storage.ts duplicate was removed in 2a1cc6f, leaving
@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner unreferenced.
Uninstalling shrinks the dep tree and prevents accidental future
imports of S3 SDKs into client-bundled code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9aeaae61 docs: ADR-0002, runbooks, and deferred items for MinIO Juan Vidal 2026-05-08 ↗ GitHub
commit body
- ADR-0002 captures the MinIO + provider-agnostic-storage decision,
  consequences, and alternatives, in the same shape as ADR-0001.
- local-development runbook: drop the "needs an R2 account" prereq,
  document the MinIO services in step 1, note that the pre-populated
  R2_* env block targets local MinIO out of the box.
- architecture runbook: storage line now mentions MinIO locally; add
  lib/storage.ts to the backend file map.
- deferred.md: pin MinIO image tags, R2_* → S3_* rename, frontend
  lint baseline, and the next/opennextjs peer-dep conflict that
  surfaced when uninstalling unused AWS SDK deps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
596ee51f chore: drop unused resend dep, smooth local-dev onboarding Juan Vidal 2026-05-08 ↗ GitHub
commit body
- Uninstall the 'resend' package from both backend and frontend.
  Zero source references in either tree; RESEND_API_KEY was env-only
  ceremony for a feature that doesn't exist yet (email is in
  docs/deferred.md as a future item).
- Drop RESEND_API_KEY from backend/.env.example and add a comment
  clarifying that LLM keys are optional for first-run exploration.
- Runbook updates:
  - Prerequisites: LLM keys marked optional with what works without one.
  - Step 1: note that db/init/01-extensions.sql enables pgcrypto on
    first Postgres boot.
  - Step 3: document --legacy-peer-deps requirement for frontend
    npm install (cross-references the deferred item).
  - Step 5: drop Resend from the fillables list, clarify LLM keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3709a5a6 Merge pull request #1 from juanjo/feat/local-mike Juan Vidal 2026-05-08 ↗ GitHub
Make Mike runnable locally: Postgres + Auth.js + MinIO

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-187.md from inside the repo you want the changes in.

⬇ Download capture-thread-187.md