mnswpr/docs/deployment.md
Ayo d5109b8dc9
Some checks failed
Checks / lint (push) Has been cancelled
Checks / test (push) Has been cancelled
Checks / content (push) Has been cancelled
chore: update readme
2026-07-18 22:26:19 +02:00

5.8 KiB

First-time deployment

Everything needed to take this repo from a fresh clone to a live deploy of mnswpr.com. Once it's set up you won't need this again — day to day, pnpm release is the whole story.

Two services are involved: Netlify hosts the site, Firebase (Firestore) stores the leaderboard. Both are driven entirely from the CLI; nothing here requires a web dashboard except one Netlify setting noted below.

For the conceptual split between infra config (committed, declarative) and infra tools (pinned devDependencies), see AGENTS.md → "Infra".


0. Prerequisites

pnpm i     # installs firebase-tools and netlify-cli as pinned devDependencies

Both CLIs are invoked through pnpm exec, so you never need a global install.


1. Netlify

pnpm exec netlify login
pnpm exec netlify link      # binds this directory to the site; writes .netlify/ (gitignored)

If you know the site ID you can skip the prompts:

pnpm exec netlify link --id <site-id>

Losing .netlify/ is harmless — it's local state. Re-run netlify link.

Set the base directory

The site's base directory must be the repo root. This is the one setting that isn't in a config file — it lives on the site itself (Site configuration → Build & deploy → Base directory) and must be empty.

If it points at a subdirectory that doesn't exist, git-triggered builds fail before they start.

Set the environment variables

This is the step most likely to be missed, because it only affects one of the two deploy paths:

  • pnpm run deploy:site builds locally and uploads dist/. It reads your local, gitignored .env.production — Netlify's env vars are never consulted.
  • pnpm release force-pushes the release branch, and Netlify builds it from git. That build runs on Netlify's machines with no access to any local file, so it needs the variables set on the site.

A site that deploys fine via deploy:site can still ship a broken build from git if these are missing — the Firebase config comes out undefined and the leaderboard fails for every visitor.

The eight values are the same ones committed in .env.development: prod and dev are the same Firebase project (see firebase/.firebaserc), separated only by collection namespace. So you can set them straight from that file:

grep -E '^VITE_FIREBASE_' .env.development | while IFS='=' read -r k v; do
  pnpm exec netlify env:set "$k" "$v"
done

That covers:

VITE_FIREBASE_API_KEY            VITE_FIREBASE_STORAGE_BUCKET
VITE_FIREBASE_AUTH_DOMAIN        VITE_FIREBASE_MESSAGING_SENDER_ID
VITE_FIREBASE_DATABASE_URL       VITE_FIREBASE_APP_ID
VITE_FIREBASE_PROJECT_ID         VITE_FIREBASE_MEASUREMENT_ID

Two variables are deliberately not in that list:

  • VITE_LB_NAMESPACE is already set to mw in netlify.toml, so it ships with the repo. (src/main.js defaults to mw-test when it's missing, so a misconfigured build writes to the test board, never production.)
  • VITE_FIRESTORE_EMULATOR must stay absent or empty in production. src/main.js treats 1/true/yes as "connect to a local emulator", so if it leaks into the site's environment the live leaderboard silently tries to reach 127.0.0.1:8080 and fails for everyone. It belongs only in .env.development.

Verify what's actually set:

pnpm exec netlify env:list

These are not secrets. Firebase Web API keys are public by design — they identify the project, they don't authorize anything. Access is governed by firebase/firestore.rules. They're kept out of git as prod hygiene, not because exposure is dangerous; the dev values are committed for this reason.


2. Firebase

Log in

pnpm exec firebase login

Deploy the security rules

Do this before the first real release. firebase/firestore.rules is the source of truth for who can read and write the leaderboard, but it only takes effect once deployed — a project can be running rules set by hand in the console long ago, which won't match the repo.

pnpm run deploy:db     # firebase --config firebase/firebase.json deploy --only firestore

That deploys rules and indexes. Note that prod and dev are the same Firebase project, so a rules deploy affects both environments at once.

If the rules are stale, leaderboard writes fail with permission-denied even though the site loads fine — worth confirming after the first deploy by finishing a game and checking the score appears.


3. Deploy

Two paths, both supported:

pnpm run deploy:site   # build locally, upload dist/ via the Netlify CLI

or the full release, which is what tags a version and triggers the git build:

pnpm release           # lint + test, then bumpp, then sync the release branch

pnpm release runs scripts/release.js, which force-pushes main to the release branch on the gh remote. That push is the deploy — Netlify watches that branch. It refuses to run from a branch other than main or with a dirty working tree.


Verifying a first deploy

  1. pnpm exec netlify env:list shows all eight VITE_FIREBASE_* and no VITE_FIRESTORE_EMULATOR.
  2. The site loads and the version in the heading matches package.json.
  3. Finish a game — your score appears on the board. This is the real end-to-end check: it exercises the env vars, the rules, and the namespace together.
  4. The leaderboard shows the mw namespace, not mw-test.