Salpointe Film & TV ProductionsSalpointe Film & TV
← All playbooks
Role Playbook

Platform Developers playbook.

You are the two people who can change this website. Here is how it is built, how to run it on your own laptop, and how to ship a change without taking it down during a game.

01

What you're actually taking over

This site is two programs that talk to each other. The part you see in a browser is a Next.js app. The part that stores things and enforces the rules is Convex. Everything else — sign-in, email, hosting — is a service bolted onto those two.

It is a real production system, not a class project. Clubs book the crew through it, families get email from it, and gear worth more than a car is checked in and out through it. That is the fun part and it is also the reason for the rules further down.

02

The five pieces, and where each one lives

  • Next.js 16 (App Router)src/app/. Every folder in there is a URL. src/app/games/page.tsx is the page at /games. Shared UI lives in src/components/.
  • Convexconvex/. The database and all the server code. convex/schema.ts defines every table; each other file holds the queries and mutations for one feature. This is where permission checks live.
  • Better Auth + Googleconvex/auth.ts. Sign-in is Google only and locked to @salpointe.org. There are no passwords anywhere in this system, which is deliberate: no passwords means nothing to leak, and when the school disables an account it dies here too.
  • Resendconvex/email.ts and convex/lib/emailTemplates.ts. Every automatic email — call sheets, checkout confirmations, the notice parents get — is built there.
  • Cloudflare Workerswrangler.jsonc. Where the Next.js app runs once it's deployed, via the OpenNext adapter.
03

Get it running on your laptop

You need Node installed and access to the repo. Two terminals, both left running while you work.

  1. Install the dependencies once:
    npm install
  2. First terminal — Convex. This watches convex/ and pushes your changes to the dev backend the moment you save.
    npx convex dev
  3. Second terminal — the website itself, at http://localhost:3000.
    npm run dev
  4. Sign in at /sign-in with your school Google account. You'll come in as a student admin, same as on the live site.

Dev and live share a backend right now

Until the production cutover happens, your local site and the real site read the same Convex deployment. That means a test event you create on localhost shows up on the live site. Create test junk with an obvious name and delete it when you're done.
04

How a change flows

You almost never write code that fetches data. A page calls useQuery(api.games.listUpcoming) and Convex pushes new results whenever the underlying rows change — so when someone claims a camera slot, every open browser updates itself. No refresh button, no polling loop. If you find yourself writing one, you've misunderstood something.

  • Editing something in convex/? npx convex dev pushes it in about a second. A schema mistake fails loudly there — read that terminal.
  • Editing something in src/? The browser hot-reloads.
  • Added a brand new page folder? Run npx next typegen so the route types know it exists, or TypeScript will insist your own link is invalid.
05

Five rules that are not negotiable

  • Never commit a secret. API keys and client secrets live on the deployment, not in the repo. Set them with the value left off so the terminal prompts for it and it never lands in your shell history: npx convex env set RESEND_API_KEY. If you ever paste a key into a file, tell Mr. Rivers immediately — it has to be rotated, and that is a five-minute fix that becomes a big problem if nobody says anything.
  • Never commit other people's data. reference-data/ is ignored by git because it holds SkillsUSA rankings and résumés with other schools' students' names in them. Those are minors. They do not go on the public internet because it was convenient.
  • Nothing you deploy may exceed 25 MiB per file. Cloudflare refuses the whole deploy over that — one oversized PDF and the site doesn't ship. Compress video and PDFs before they go in public/.
  • Permission checks go in the Convex function. Hiding a button is not security — the mutations are a public API and anyone can call them from a console. Every privileged function starts with requireCapability(ctx, ...) or requireAdmin(ctx). See convex/lib/permissions.ts, which is worth reading in full.
  • Real logic goes in a plain file you can test. Look at convex/lib/gameRules.ts or convex/lib/skills.ts: no React, no database, just functions. That's the pattern here, because logic buried in a component can only be checked by clicking around and hoping.
06

Shipping a change

Work on a branch, never straight on main. Before you ask for it to go out, both of these must come back silent:

npx tsc --noEmit -p .
npx eslint convex src
npm test

npm test runs the checks in tests/. They cover the rules that a type checker can't see — who is allowed to do what, and whether a "verified" skill really means a teacher signed it. If you change either, expect them to fail until you've decided what the new rule is.

Then commit, push the branch, and tell Mr. Rivers what changed and what you checked. Deploying to the live site is one command, and it is his call when to run it:

npm run deploy

Don't deploy during a game

Coverage claims and call sheets are happening in real time on Friday nights. A deploy takes the site down for a few seconds and rebuilds every page. Ship on a weekday afternoon.
07

When something's broken

Check in this order — it goes from most to least likely.

  1. Is it actually broken, or are you looking at a stale tab? This has fooled us. Hard-reload, or check what the server is really sending:
    curl -s https://salpointe-film-club.jetnoirsystems.workers.dev | head -40
  2. Convex dashboard logs. If a mutation threw, the error and stack are there. Most "the button does nothing" bugs are a mutation throwing.
  3. The browser console. For anything visual or client-side.
  4. Worker logs for a page that won't load at all:
    npx wrangler tail

Errors students see are deliberately cleaned up on their way out — see src/lib/convexError.ts. If you add a new failure case, write the message for the student who hits it, not for yourself.

08

Things you must not change on your own

Ask first — every time

  • convex/lib/permissions.ts — the list of what student admins can do. You are student admins. Widening it is exactly the change you shouldn't be able to make quietly, and by design you also cannot grant roles in the app.
  • Production environment variables, the Google OAuth credentials, and anything DNS. Breaking those locks the whole school out, and fixing it needs accounts you don't have.
  • Anything in convex/lib/emailTemplates.ts that goes to parents. That wording quotes the Parent/Student Handbook on purpose.
  • Deleting data. There is no undo on a Convex delete. If a table needs cleaning up, write the script, show it to him, then run it.
09

Read next

  • README.md — the long version of all of this, including how sign-in is locked down and how the b-roll on the landing page is encoded.
  • docs/PRODUCTION-RUNBOOK.md — the plan for moving to film.salpointe.org with its own backend.
  • AGENTS.md and CLAUDE.md — the notes that tell an AI assistant how to work in this repo. Read them before you use one here; they exist because this Next.js version and Convex both changed things that most models still get wrong.
  • The other two playbooks below, so you know what the producers are trying to do with the tools you maintain. Most feature requests will come from them.

Want to see the permission model in action? Your dashboard is shorter than Mr. Rivers'. That's the code in permissions.ts doing its job.

The other playbooks