# crumbs

## dev

prereqs: bun, docker, ios simulator (or device + ngrok)

```sh
bun install

cp api/.env.example api/.env
cp mobile/.env.example mobile/.env
# fill

bun run infra:up
bun run db:migrate
bun run db:seed  # optional: a stockholm-flavoured dev dataset for me@seed.crumbs.test

bun run api:dev
bun run mobile:start
```

physical device: run `bun run api:tunnel` and set both `PUBLIC_API_URL` (api) and `EXPO_PUBLIC_API_URL` (mobile) to the ngrok url so magic-link emails resolve.

## avatars / media storage

user avatars are processed server-side (re-encoded to a 512px webp, exif stripped) and stored in object storage. the client pre-crops + downscales for upload bandwidth; the server is the security boundary.

`STORAGE_DRIVER` selects the backend:

- `disk` (default) — writes under `UPLOADS_DIR` and serves them at `PUBLIC_API_URL/static`. zero setup, used for local dev + tests.
- `r2` — cloudflare r2. create a bucket, an api token (access key id + secret), and expose the bucket publicly via a custom domain (or the `r2.dev` url). set `R2_ENDPOINT`, `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`, `R2_BUCKET`, and `R2_PUBLIC_BASE_URL`. objects are content-addressed and immutable, so a long edge cache rule is safe.

## scripts

- `bun run ok` — tsck + lint + format check + tests
- `bun run db:generate --name <change>` — generate a migration from `core/db/schema.ts`; always pass `--name` so it gets a descriptive filename (e.g. `crumb_images`), never the random default
- `bun run db:seed` — seed a local dev dataset (idempotent); log in as `me@seed.crumbs.test`
- `bun run db:studio` — drizzle studio
- `bun run infra:down` — stop docker services
- `bun run infra:teardown` — stop services + drop volumes (wipes db)
