Context
A non-profit runs an executive-functioning curriculum in schools, lessons on focus, emotional regulation, and time management, taught by regular classroom teachers rather than specialists. The program is only as good as its delivery: if teachers skip lessons, rush them, or the material doesn't land, nobody finds out until the year is over.
The problem
Planning and delivery lived across disconnected documents and spreadsheets. The organization could not answer basic operational questions: which lessons were actually delivered, in which grades, by which teachers, how long each one took to prepare and to teach, and how teachers rated them.
What I owned
The full build, solo: data model, authorization, both role experiences, the analytics layer, and the deployment pipeline. Built with Next.js and Supabase, with plain token-based CSS instead of a UI framework.
How it works

Key decisions
- Authorization lives in the database, not the UI. Row-level security policies are the authorization layer, so a teacher cannot read another teacher's classes or feedback even if a page or an API route were wrong. The app-level checks are a convenience on top, not the actual guarantee.
- No UI framework. The portal runs on low-spec school Chromebooks, so I wrote plain token-based CSS ported from the brand system instead of shipping a component library. Fast first render, no dependency to maintain, and WCAG AA contrast throughout.
- The portal indexes content, it doesn't host it. Lesson material stays where the team already maintains it. Rebuilding a document system would have doubled the scope and given the client something worse than what they had.
- Two roles, deliberately. Admin and teacher. Every request for a third role got pushed back until the pilot proved it was needed.

Verification & delivery
74 unit test files plus Playwright end-to-end coverage, CI on every change, and a promotion workflow enforced by GitHub Actions so nothing reaches production without passing through staging first. Database changes ship as versioned migrations, 24 of them so far.
Outcome
In pilot with a school district across two grade levels. The program team can now see, without asking anyone, how much of the curriculum has been delivered, how teachers rate each lesson on preparation, engagement and content, and where preparation time is out of line with classroom time.
What I'd improve today
The analytics answer "what happened". The next useful step is "what needs attention": flagging a class that has fallen behind pace, or a lesson that consistently rates low, instead of leaving an admin to spot it in a table.