Skip to main content

Working Session: Local Dev & the Contribution Workflow

Pixel art side-scrolling level. Left: a developer at a cluttered laptop in warm amber tones, tangled in Docker icons and a loading spinner. A glowing teal path runs right through four checkpoints — a git branch, a pull request, CI with a green check, and two people doing code review — arriving at a cool blue server with a green light and a small crowd of happy users. Tagline: From Your Laptop to Real Users.

Reminders​

  • OPEN: The Ticket Hunt — due Wed Sep 16
  • OPEN: Project Bids — due Thu Sep 17
  • OPEN: Onboarding: Gradebook Column Groups — due Thu Sep 24

CS 4535: Software Design & Delivery

Working Session: Local Dev & the Contribution Workflow​

©2026 Jonathan Bell, CC-BY-SA

Learning Objectives​

After this session, you'll be able to:

  1. Run Pawtograder locally against a seeded database
  2. Trace a change through branch, PR, CI, review, merge and deploy
  3. Claim a hunt role, and say what makes a ticket somebody can act on
  4. Know where and how to ask for help when stuck

You Leave This Room With Two Things​

1. Pawtograder running on your machine

2. A hunt role with your name on it

Everything else this semester is downstream of those two facts.

Two Ways to Run Pawtograder​

Split diagram. Path A, frontend only: a Next.js dev server on localhost:3000 pointing at a shared staging backend in the cloud — minutes to start, no Docker, cannot change the schema. Path B, full local stack: the same dev server plus Docker containers for Postgres, Auth, Realtime and Storage, and Edge Functions, with Supabase Studio on port 54323 and a mail catcher on 54324 — slower to start, required for migrations and end-to-end tests.

Which One Do You Need?​

If your work touches…You need
Docs, copy, a component, a page layoutPath A — staging backend
A database migration or an RLS policyPath B — full local
An edge functionPath B — full local
Playwright end-to-end testsPath B — full local
Anything you aren't sure aboutStart with A, escalate

Signups are disabled on staging. In a local instance, any email works — and putting instructor in the address makes you an instructor.

Path A: Frontend Against Staging​

git clone https://github.com/pawtograder/platform
cd platform
nvm install 22 && nvm use 22
npm install # ignore the deprecation wall
cp .env.local.staging .env.local # nothing to fill in
npm run dev # https://localhost:3000

Your browser will warn you about the self-signed certificate. That's expected — click through. HTTPS is required for camera and microphone access in the help queue.

Sign in with email and password. OAuth on staging redirects to the deployed site, not your laptop.

Every command on the next few slides also lives at /docs/local-dev.

Path B: The Full Local Stack​

# Docker must be running first
npx supabase start # boots Postgres, Auth, Realtime, Storage
npx supabase db reset # replays 400+ migrations, loads base data

# the CLI's key names are not the app's. Rename them on the way out:
npx supabase status -o env \
--override-name api.url=NEXT_PUBLIC_SUPABASE_URL \
--override-name auth.anon_key=NEXT_PUBLIC_SUPABASE_ANON_KEY \
--override-name auth.service_role_key=SUPABASE_SERVICE_ROLE_KEY >> .env.local

npm run seed # a test class with real logins
npm run dev

# only when you're exercising an edge function:
npx supabase functions serve --env-file .env.local

Then three by hand, which no command emits: SUPABASE_URL and SUPABASE_ANON_KEY (same values, without the NEXT_PUBLIC_), and ENABLE_SIGNUPS=true.

Then: app on https://localhost:3000 · Studio on localhost:54323 · captured mail on localhost:54324

dev Is For Editing. Otherwise, Build.​

npm run dev              # compiles each route on first hit
npm run build && npm start # a few minutes, then fast everywhere

next dev recompiles per route as you click. Fine while you're editing one page. Painful when you're exploring the app as four different roles, and fatal for a Playwright run.

NEXT_PUBLIC_* is baked into the bundle at build time. Change it, delete .next, rebuild. And never run dev and start at the same time.

The Three Gotchas​

  1. Your database is older than your checkout. Symptoms all differ, cause is one: column ... does not exist, Could not find the '...' column in the schema cache, no partition of relation "audit" found for row. Fix: npx supabase db reset, then npm run seed. If start restored a stale volume, npx supabase stop --no-backup first.
  2. Wrong Supabase CLI. The CLI is pinned to 2.105.0 in package.json. On older versions db reset dies with must be owner of table objects. Use npx, never a global install.
  3. You changed the schema and skipped npm run client-local. The generated types still describe the old schema, so you get type errors that point anywhere except at your migration.

Schema change, in full: npx supabase migration new <name> · write the SQL · npx supabase db reset · npm run client-local

All three are written down in AGENTS.md. Point your agent at that file.

Work Block: Get to the Checkpoint​

10 minutes. Staff are circulating.

The checkpoint: you're logged in to a course as a seeded user and can see an assignment.

Every command is at /docs/local-dev. Don't retype from the slides.

If you get there: help the person next to you.

If you are stuck: raise a hand. Don't silently debug — that's what the rest of the semester is for.

The Path of a First PR​

Pipeline diagram flowing left to right through six stages — branch, pull request, CI, review, merge to main, deploy. CI branches into lint and prettier, Jest unit tests, Deno function tests, Playwright with Argos visual snapshots, and a preview deploy. Review branches into peer review and staff review; deploy notes the Helm chart to the cluster. Orange feedback arrows loop back from CI on a red build and from review on requested changes.

What CI Protects​

CheckWhat it catches
npm run lintESLint violations, and unformatted code
JestUnit-level regressions
npm run test:functionsDeno tests for the edge functions
Playwright (~100 tests)A user flow that stopped working
ArgosA page that changed appearance without anyone deciding to
Preview deployYour branch, running, at a URL commented on the PR

Run npm run format before you commit. CI rejects unformatted code, and that round trip is a wasted twenty minutes.

Branch in the repo, not in a fork. The E2E lane won't run for a fork PR.

What a Good PR Looks Like Here​

Gets merged

  • One concern, reviewable in one sitting
  • Description says what changed and why
  • Links the ticket
  • Green CI before you ask for review
  • Says how you tested it

Sits for a week

  • Four unrelated changes in one branch
  • Description is the branch name
  • Red CI, awaiting review
  • A formatting sweep mixed into a feature
  • No indication anyone ran it

Your git history is the evidence for your band claim in December, and a professional record besides.

Claim Your Role​

The hunt has four roles: the student, the grader, the instructor, the new contributor. You already have the student role. Claim a second one here, so all four get covered.

The new-contributor role expires. You're a new contributor exactly once, and it's this week. By October you'll know too much to see what the setup docs leave out.

What Makes a Fileable Ticket​

File this

  • Numbered steps a stranger can follow
  • What you expected, and what happened
  • Who it affects, and what it cost them
  • Evidence: a screenshot, a trace, a log line

Not yet

  • "This file uses any forty-one times"
  • A symptom with no user in it
  • Something you couldn't reproduce
  • A duplicate one search would have found

Hunt in the area you're curious about. Your bid on 9/17 will be much better for it.

The Other Half: Triage​

Two tickets filed, and two things somebody hasn't decided about, decided. Every triage reaches one of three verdicts:

  1. Still real. The reproduction, who it affects, a size. It becomes claimable.
  2. No longer real. Fixed, obsolete, or a false positive. Say how you know.
  3. Undecidable without something I don't have. Name what you'd need and who has it.

The verdict earns nothing. The reasoning is the deliverable.

Session Capture: Install Entire​

Required on every repo you work in this semester. One install, one enable, then it rides along on git push.

# macOS / Linux
brew tap entireio/tap && brew trust entireio/tap
brew install --cask entire
# no Homebrew: curl -fsSL https://entire.io/install.sh | bash
# Windows, PowerShell 5.1 or later
irm https://entire.io/install.ps1 | iex
cd platform
entire enable --local \
--checkpoint-remote github:neu-cs4535/fa26-entire-checkpoints
entire status # checkpoint destination must be the corpus repo

It hooks whichever agent you use and stores each session beside the commit it produced. Transcripts go to a private course repo, never to pawtograder/platform. Who reads them, and how to opt out of the research half: syllabus.

Already have the stack running? Give your agent one small task, commit it, then read back what got captured: entire checkpoint list, then entire checkpoint explain <id>.

Work Block: Get Wired Up, Claim Your Role​

8 minutes. Four things, in this order.

  1. Link your GitHub handle to your Pawtograder account. Without it we can't credit anything you file.
  2. Open the column-groups assignment and confirm your fork of the handout repo exists.
  3. Enable session capture. The two commands on the last slide, then entire status to confirm where checkpoints are going.
  4. Claim your second role so all four get covered.

If any of the four didn't work: tell me now, not on Monday.

The 30-Minute Rule​

Thirty minutes of no progress on the same problem, and you owe the team a question.

Not because struggling is bad — struggling is where the learning is. But because silent struggling is invisible to everyone who could have unblocked you in ninety seconds.

The failure mode isn't asking too early. It's a student who says nothing for eight days.

How to Ask​

Four lines. That's the whole template.

  1. What I'm trying to do
  2. What I did
  3. What I expected, and what happened instead — paste the actual error
  4. What I already ruled out

Not: "supabase isn't working, any ideas?"

Instead: "Running db reset to get the seeded class. It fails at migration 2026… with must be owner of table objects. I checked I'm on the pinned CLI via npx. Full log in the thread."

Where to Ask​

WhereFor what
DiscordSetup problems, "is this expected?", anything fast
The ticket itselfScope questions — they belong in the thread, permanently
Monday clinicDesign tradeoffs, architecture, "we're stuck as a team"
/docs/local-devEvery command from today, plus seeding, migrations, edge functions
The repoREADME.md, AGENTS.md, CLAUDE.md, DEPLOYMENT.md — read first

Ask in public by default. Your question is somebody else's answer next week.

Key Takeaways​

  1. Pick your path deliberately. Staging for frontend and docs; the full local stack the moment you touch the schema, an edge function, or E2E.
  2. Small, green, well-described PRs get merged. Everything else waits.
  3. Thirty minutes, then ask — in public, with the error pasted.

You have a running app, a role, and everything wired up. Now go find what's wrong.

Up Next​

Mon Sep 14 — Architecture II: Supabase, RLS & Student-Data Privacy

You now have a local database with seeded students in it. Monday: why every row checks your badge, why that check is expensive, and what FERPA obligates you to.

Before then:

  • The Ticket Hunt — two filed, two triaged, due Wed Sep 16
  • Project Bids — due Thu Sep 17
  • Column groups is open the whole time. Don't start it on Sep 23