This is an app for planning dinners for Madeleine and Aslak. At it's core it solves two problems:
- What dinners can we make?
- What did we plan to make on what day?
Number 2 is pretty straight forward, we just record what dinner was planned for what day and that's that. For number 1 we are specifically interested in having a list of dinners that we like to make as an inspiration when we make our dinner plans. We are not trying to solve the issues of figuring out what can be created with our current ingredients, and we are not making a recipe list (at least yet).
The web app is hosted on Vercel at PlanEatRepeat.com
- Vercel Preview deployments build the web app but never run database
migrations. Their
DATABASE_URLmust not point at production. - Vercel Production builds the app first, then runs
prisma migrate deploythroughMIGRATION_DATABASE_URL. A failed build or migration prevents the new deployment from being published. MIGRATION_DATABASE_URLis configured only for Vercel Production and should use a Supabase direct connection, or the session-mode pooler when a direct connection is unavailable. Do not use the transaction-mode pooler for migrations.- Production migrations must be backward-compatible with the currently deployed application. Prefer additive changes; backfill and deploy compatible application code before later removing or constraining old fields.
- Never edit, rename, or delete a migration after it has reached a shared or production database. Verify a current Supabase backup before any destructive migration.
The project was Bootstrapped with create-t3-app.
pnpm install
cp .env.example .envStart Postgres:
docker compose -f database-docker.yml up -dInitialize/seed local DB:
pnpm db:resetReset everything (destructive local reset):
pnpm db:fixThe easiest way to test the mobile app is with Expo Go on an Android phone, with the phone and your Mac on the same Wi-Fi network.
- Install Expo Go from the Play Store on the phone.
- Set up the mobile env file:
cp apps/mobile/.env.example apps/mobile/.envFill in EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY (same Clerk dev instance as the web app). Leave EXPO_PUBLIC_API_URL commented out — the app infers your Mac's IP from the Metro connection.
- Start the database and web API on the Mac (see Local Setup above for first-time DB seeding):
docker compose -f database-docker.yml up -d
pnpm dev:web- Start the mobile dev server in another terminal:
pnpm dev:mobile- Open Expo Go on the phone and scan the QR code from the terminal.
- When the app loads, tap local login to sign in as aslakhol@gmail.com. This uses a dev-only bypass endpoint that only exists when the web server runs in development mode on a local network — no OAuth dance needed.
You should land on the Weekly Plan with the seeded dinners available. Changes you make in apps/mobile hot-reload on the phone.
- Web must run on port 3000. The app assumes the API is at
http://<your-mac-ip>:3000. If something else is squatting on port 3000, Next.js silently picks another port and the app can't reach the API — either free up the port, or uncommentEXPO_PUBLIC_API_URLinapps/mobile/.envand set it tohttp://<your-mac-ip>:<actual-port>(find your IP withipconfig getifaddr en0), then restart the mobile dev server. - macOS firewall: accept the "allow incoming connections" prompt for Node the first time, or the phone can't reach Metro or the API.
- "local login" fails with 403/404: the web server is not in dev mode, or the phone isn't hitting it over the local network. Check that opening
http://<your-mac-ip>:3000in the phone's browser shows the web app.
# run
pnpm dev:web # web
pnpm dev:mobile # mobile (QR code, for Expo Go on a physical phone)
pnpm dev:mobile:android # mobile (Android emulator/device via adb)
pnpm dev # all dev tasks
# quality/build
pnpm lint
pnpm build
# database
pnpm db:migrate
pnpm db:studio
pnpm db:reset
pnpm db:fix # destructive local reset
# screenshots
pnpm capture # web + mobile + side-by-side
pnpm capture:web # web + side-by-side (requires capture/mobile/*.png)
pnpm capture:mobile # mobile + side-by-side (requires capture/web/*.png)Use these commands to capture screenshots and compose side-by-side images.
pnpm dev:webis running onhttp://localhost:3000pnpm dev:mobile:androidis running onhttp://localhost:8081- Mobile app is logged in (tap
local loginonce after startup) adband ImageMagick (magick) are installed- Playwright Chromium is installed once:
pnpm --filter @planeatrepeat/web exec playwright install chromiumpnpm capture # full flow
pnpm capture:web # web only + side-by-side refresh
pnpm capture:mobile # mobile only + side-by-side refreshpnpm capture: verifies web and mobile dev servers, captures both platforms, then creates side-by-side images.pnpm capture:web: verifies web dev server, captures web, then re-creates side-by-side images using existing mobile screenshots.pnpm capture:mobile: verifies web and mobile dev servers, captures mobile, then re-creates side-by-side images using existing web screenshots.
capture/web/plan.pngcapture/web/dinners.pngcapture/mobile/plan.pngcapture/mobile/dinners.pngcapture/side-by-side/plan.pngcapture/side-by-side/dinners.png