Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,76 @@ Open-source release containing the Mike frontend and backend.
- `backend/` - Express API, Supabase access, document processing, and migrations
- `backend/migrations/000_one_shot_schema.sql` - one-shot Supabase schema for fresh databases

## Setup
## Run locally with Docker + local Supabase

Spins up the frontend, backend, and a full local Supabase stack (Postgres, Auth, Storage, Realtime) — no cloud account required.

Prerequisites: Docker Desktop, [Supabase CLI](https://supabase.com/docs/guides/cli) (`brew install supabase/tap/supabase`).

```bash
# 1. Start local Supabase (Postgres, Auth, Storage, etc.)
# The migration in supabase/migrations/ is applied automatically.
supabase start

# 2. Note the keys printed by `supabase start` (or run `supabase status`).
# Create env files from the examples and paste in the local values:
cp backend/.env.example backend/.env
cp frontend/.env.local.example frontend/.env.local

# 3. Start the app stack
docker compose up -d
```

Then open http://localhost:4000.

Default ports (set in [docker-compose.yml](docker-compose.yml)):

| Service | URL |
|---|---|
| Frontend | http://localhost:4000 |
| Backend | http://localhost:4001 |
| Supabase API | http://localhost:54321 |
| Supabase DB | `postgresql://postgres:postgres@localhost:54322/postgres` |
| Mailpit (auth emails) | http://localhost:54324 |

Env values for the local Supabase stack:

```
# backend/.env
SUPABASE_URL=http://host.docker.internal:54321 # container -> host
SUPABASE_SECRET_KEY=<secret key from `supabase status`>
R2_ENDPOINT_URL=http://host.docker.internal:54321/storage/v1/s3
R2_ACCESS_KEY_ID=<S3 access key from `supabase status`>
R2_SECRET_ACCESS_KEY=<S3 secret key from `supabase status`>
R2_BUCKET_NAME=mike

# frontend/.env.local
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321 # browser -> host
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=<publishable key>
SUPABASE_SECRET_KEY=<secret key>
NEXT_PUBLIC_API_BASE_URL=http://localhost:4001
```

Create the `mike` storage bucket once:

```bash
docker exec supabase_db_mike psql -U postgres -d postgres -c \
"insert into storage.buckets (id, name, public) values ('mike','mike',false) on conflict (id) do nothing;"
```

Lifecycle:

```bash
docker compose logs -f # tail app logs
docker compose restart # pick up env changes
docker compose down # stop the app
supabase stop # stop the supabase stack (volumes persist)
supabase db reset # wipe DB and re-run migrations
```

The compose file bind-mounts source for hot reload and runs `npm install` on container start so the deps in the named volume are guaranteed consistent (works around a Docker Desktop named-volume init quirk when bind mounts overlap).

## Setup (manual, without Docker)

Install dependencies:

Expand Down
7 changes: 7 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
dist
.env
.env.*
!.env.example
*.log
.DS_Store
18 changes: 18 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM node:22-bookworm-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libreoffice \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm install

COPY . .

EXPOSE 3001

CMD ["npm", "run", "dev"]
45 changes: 45 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: mike-backend
env_file:
- path: ./backend/.env
required: false
environment:
- PORT=3001
- FRONTEND_URL=http://localhost:4000
ports:
- "4001:3001"
volumes:
- ./backend:/app
- backend_node_modules:/app/node_modules
command: sh -c "npm install && exec npm run dev"
restart: unless-stopped

frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: mike-frontend
env_file:
- path: ./frontend/.env.local
required: false
environment:
- NEXT_PUBLIC_API_BASE_URL=http://localhost:4001
ports:
- "4000:3000"
volumes:
- ./frontend:/app
- frontend_node_modules:/app/node_modules
- frontend_next_cache:/app/.next
command: sh -c "npm install --legacy-peer-deps && exec npm run dev -- -H 0.0.0.0 -p 3000"
depends_on:
- backend
restart: unless-stopped

volumes:
backend_node_modules:
frontend_node_modules:
frontend_next_cache:
11 changes: 11 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
.next
.open-next
out
build
.env
.env.*
!.env.local.example
*.log
.DS_Store
.vercel
15 changes: 15 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM node:22-bookworm-slim

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm install --legacy-peer-deps

COPY . .

EXPOSE 3000

ENV HOSTNAME=0.0.0.0
ENV PORT=3000

CMD ["npm", "run", "dev", "--", "-H", "0.0.0.0", "-p", "3000"]
8 changes: 8 additions & 0 deletions supabase/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Supabase
.branches
.temp

# dotenvx
.env.keys
.env.local
.env.*.local
Loading