local-development

Running functions and web app locally, troubleshooting emulator issues, Storybook. Use when running or debugging locally.

SKILL.md

GitHub

Local Development

When to Use

Use this skill when running the web app or functions locally, troubleshooting emulator issues, or running Storybook.

Important

The user runs functions and web app locally for testing. Claude writes code and creates PRs -- Claude does NOT deploy or run dev servers.

Running Functions Locally (user runs this)

pnpm exec nx run functions:serve

This command:

  1. Builds the functions
  2. Copies .env.dev to dist/apps/functions/.env
  3. Starts watch mode for rebuilds (background)
  4. Runs firebase serve --only functions --project=dev on port 5001

Running Web App Locally (user runs this)

pnpm exec nx run maple-spruce:dev

Runs on http://localhost:3000. On localhost the app auto-connects to the Functions emulator (port from NEXT_PUBLIC_FUNCTIONS_EMULATOR_PORT, default 5001). Auth stays on real dev by default; to run fully against emulators (auth included — e.g. sign in as a seeded emulator user), set NEXT_PUBLIC_AUTH_EMULATOR_PORT (opt-in). Next only inlines NEXT_PUBLIC_* from .env files reliably, so put these in apps/maple-spruce/.env.local (gitignored) rather than the shell. The portal e2e (tools/run-portal-e2e.sh) does exactly this.

Portal E2E (role scoping)

./tools/run-portal-e2e.sh          # emulators + next dev + Playwright

Drives the real app in a browser: seeds an admin + an mt-teacher into the emulators, signs in through the login form, asserts the role-filtered shell. First browser-level proof of the scoped-roles wiring (epic #49).

Running Storybook

pnpm exec nx run maple-spruce:storybook
# Opens http://localhost:6006

Building Storybook:

pnpm exec nx run maple-spruce:build-storybook
# Output: dist/storybook/maple-spruce

Running Unit Tests

Each project owns a vitest.config.mts; the @nx/vitest plugin infers its test target.

pnpm test                                   # nx run-many -t test: every project, cached
pnpm exec nx affected -t test               # only projects your change can affect
pnpm exec nx test domain                    # one project
pnpm exec nx test domain -- src/lib/artist.spec.ts   # one file
pnpm test:coverage                          # root run of all project configs + merged coverage (what CI gates on)

New library with specs? Give it a config, or tools/check-vitest-projects.ts fails CI: pnpm exec nx g @nx/vitest:configuration --project=<name> --testEnvironment=node. Its generated config uses the deprecated nxViteTsPaths()/nxCopyAssetsPlugin(); swap them for tsconfigPaths() from vite-tsconfig-paths like every other config here.

Running Integration Tests (user runs this)

Integration tests run Cloud Functions against real Firebase emulators. Requires Java installed (for Firestore emulator).

All-in-one (builds functions, copies .env, starts emulators, runs tests, shuts down):

pnpm exec nx run functions-integration-tests:e2e-with-emulators

Manual (useful when iterating on tests — keep emulators running):

# Terminal 1: Build and start emulators
pnpm exec nx run functions:build
cp .env.dev dist/apps/functions/.env
firebase emulators:start --project=dev --only auth,firestore,functions

# Terminal 2: Run tests (repeat as needed)
pnpm exec nx run functions-integration-tests:e2e

Emulator ports: Auth (9099), Firestore (8080), Functions (5001), UI (4000)

Deployment

User decides when to deploy to dev. Production deploys automatically via CI/CD on merge to main.

Troubleshooting Local Functions

Emulator prompts for environment variables

The Firebase emulator is not finding the .env file. This happens when:

  • The build clears dist/apps/functions/ before the .env is copied
  • A stale watch process is interfering

Fix:

# Kill any stale processes
pkill -f "firebase serve"
pkill -f "nx run functions"

# Clean and restart
rm -rf dist/apps/functions
pnpm exec nx run functions:serve

Why this happens:

  • Firebase reads .env from dist/apps/functions/
  • The nx run functions:build clears this directory
  • The serve command copies .env.dev after build, before starting the emulator
  • If ordering is wrong or stale processes exist, the emulator starts without the .env

Key indicator it's working:

i  functions: Loaded environment variables from .env.