My kid is learning to play piano, and I wanted a simple way to see progress through the books: which pieces have we tried, which ones need more work, and which ones feel well learned?

The books already have progress charts. I wanted to bring that idea onto a phone, with a little more detail than a sticker next to a title. A piece might be fluent but still need work on dynamics. I also wanted to look back at earlier assessments instead of replacing yesterday’s rating with today’s.

That became Little Piano, a small web app built with Codex. The scope was deliberately narrow: one child, one adult, a shelf of piano books, and a way to record progress. The child uses it within my signed-in session. No teacher accounts, invitations, payments, audio uploads, or AI grading.

The app is deployed at little-piano.vercel.app, and the code is on GitHub. The website has a public address; the learning records are protected by login and database access rules.

I started by describing the experience I wanted. Sign in, create my child’s profile, choose a book, see the songs in order, tap one, and record an assessment. I also gave Codex the technical constraints: Vue 3, Vite, TypeScript, Supabase, responsive CSS, and local development before deployment.

I asked it to inspect the existing folder first, implement the app rather than stop at a plan, create versioned SQL migrations, and run meaningful tests. Some constraints were particularly useful: never make private data public just to avoid login, never silently fall back to mock data when Supabase fails, and never apply remote migrations or deploy without instruction.

Those details gave us something concrete to review. I could respond to a working implementation and correct the assumptions as we went.

The rating design was one example. My first request used one overall score, from one to three stars. During development I changed that to three dimensions: fluency, dynamics, and rhythm. Each gets its own score:

  • One star: getting started.
  • Two stars: almost there.
  • Three stars: well learned.

No assessment is a separate state. It should never look like a one-star performance. Each save creates a new assessment, and the app shows the latest one beside the song. It does not pick the highest score from history. A piece counts as well learned when all three dimensions in its latest assessment have three stars.

That change was easier to make while we were still designing the app and had no assessment history to migrate. It also reminded me that I needed to stay involved in the product decisions, even when Codex was doing the implementation.

The stack follows the size of the problem. I wanted something I could maintain without operating a server or building a separate account-management system.

Choice Why it fits this app
Vue 3 Components and reactive state suit the book shelf, song list, and rating form.
Vite A straightforward local development server and a static production build.
TypeScript Helps keep the book, song, and assessment structures consistent as the design changes.
Supabase PostgreSQL, authentication, and a browser-accessible API in one managed service.
GitHub Source history, reviewable changes, and automated checks.
Vercel Hosts the frontend and deploys from the GitHub repository.

Vue’s documented setup supports Vite and TypeScript together. For this private progress tracker, I did not need server-side rendering or search-engine indexing of the app screens. A browser-rendered frontend was enough.

Supabase made sense because the data is relational: books contain songs, a child selects books, and assessments refer to a song within a selected book. I also already had a free Supabase project. Using it avoided creating a custom backend just to handle login and these few data operations.

The runtime path is simple:

Phone browser → Vue app hosted on Vercel
                        ↓
             Supabase Auth + PostgreSQL

The browser uses the Supabase publishable key and the adult’s authenticated session. The key is not what makes the records private. PostgreSQL row-level security checks ownership. Catalogue metadata is readable by authenticated users, while progress belongs to the owner of the child’s profile. Ordinary browser clients cannot edit the catalogue or transfer ownership.

There are database checks too: ratings must be integers from one to three, and an assessment cannot attach a song from another book. Keeping those rules in the database means a modified browser request cannot simply bypass a disabled button.

Free hosting was a practical starting point, with limits I needed to understand. These are the services I chose for a small, personal, non-commercial app, with plan details checked on 26 September 2026:

Service Free option and trade-off
GitHub Free Includes public and private repositories, plus an Actions allowance. Enough to start with source control and a small test workflow.
Supabase Free Includes a 500 MB database allowance per project. Low-activity free projects can be paused, so free hosting is not a promise of uninterrupted availability.
Vercel Hobby Intended for personal, non-commercial projects, with usage limits. Fits this family app, but I would reassess the plan if it became a commercial product.

The current terms are on the GitHub pricing page, Supabase pricing page, Supabase project-pausing guide, and Vercel pricing page. I kept the default Vercel domain rather than buying a custom one.

By “free,” I mean the hosting plan choices for this small workload. I am not counting Codex access, development time, or future usage beyond the included limits. The app stores small text records and ratings, with no recordings or sheet-music files, which helps keep its infrastructure needs modest.

The catalogue took more judgement than I expected. I wanted the songs preloaded, so adding a book would not become a manual data-entry job. I asked Codex to research Piano Adventures publisher pages, contents lists, and teaching resources, keeping source URLs and verification dates.

The first lists did not match my kid’s books closely enough. Piano Adventures has different levels, book types, and regional editions. A publisher audio list can be useful evidence without being a complete contents list for the exact printed book in front of us.

I asked Codex to use Playwright and screenshots to inspect the publisher’s previews. That found more entries, but several contents lists remained incomplete. When it suggested expanding to another publisher’s previews, I kept the research limited to Piano Adventures.

Then I photographed the progress charts in our actual books and supplied them one by one. Those photos made the edition differences visible. In Level 2B Lesson & Theory, for example, the earlier audio-based list included “Camptown Races Duet” and “Boom Boom!” The printed chart had “I’ve Got Peace Like a River” and “Deep River.” Those are different pieces, so the correction needed new entries rather than relabelling old assessment records.

We narrowed the catalogue to My First Piano Adventure Lesson Books A, B, and C, plus the Lesson & Theory and Technique & Performance books for Levels 1, 2A, and 2B. Levels 3 and 4–5 came out of the active selection.

The result is nine books and 464 learning entries. That number includes exercises and theory activities as well as songs. The six photographed All-in-Two charts are reconciled, while the My First lists retain their publisher-chart verification. “Complete” here means coverage of the progress-chart entries, not proof of every subsection or printing. Page ranges remain ranges where an exact start page is unknown, and the photographs do not establish the ISBN or printing when the cover and copyright page are absent.

Only catalogue metadata goes into the app. The photographed pages, sheet music, recordings, and publisher artwork are not distributed with it.

That was probably the most useful part of working with Codex: it could research, transcribe, reconcile IDs, regenerate the seed, and run checks. I still needed to compare its output with the real books and decide which source matched our situation.

Getting it onto my phone was a separate step from getting it running locally. Codex prepared the code and SQL; I applied the reviewed database setup in Supabase. We uploaded the project to GitHub, then I imported the repository into Vercel and configured the two frontend environment variables there.

Google sign-in needed the deployed app address in Supabase’s redirect configuration. The Google OAuth callback still points to Supabase. The local .env.local file stays out of Git, and administrative credentials do not belong in the frontend.

I also learned to separate deployment from testing. Vercel’s GitHub integration can deploy a push to the production branch without a GitHub Actions workflow. The connection between the services provides that trigger. A local commit alone does not. Vercel documents that Git workflow here.

We added a CI workflow and a shared npm run check command for unit tests, database tests, type checking, and the production build. The prepared Vercel configuration runs that same command before publishing. GitHub Actions and Vercel are independent, so a passing GitHub check should not be assumed to be something Vercel waits for automatically.

Locally, 26 unit tests and 59 PostgreSQL checks passed, along with the production build. The database tests exercise saving and loading assessments, selecting the latest rating, rejecting invalid scores and mismatched songs, and denying private records to anonymous or unrelated users. They run against PGlite, an isolated PostgreSQL engine, rather than writing test data into the live project. Real OAuth and phone testing remain separate checks.

Database deployment also remains separate. Pushing frontend code does not apply SQL migrations or update the catalogue seed. Since I initially used Supabase’s SQL Editor, any future automated migration workflow will need to reconcile migration history first. For now, reviewed database changes are manual.

The next feature I want to design is a certificate that my kid can keep and revisit. I want to design the template myself, then let the app fill in the child’s name, book, and date. That is still a design discussion, not a finished feature. It raises another useful question: finishing a book may deserve an adult decision, because dynamics and rhythm scores do not make equal sense for every theory activity.

Little Piano has given me a manageable way to build something for my family while learning how Codex fits into the process. The useful rhythm has been to describe a small need, let it implement something concrete, inspect the result, and bring better evidence when an assumption is wrong. My next step is to try the app alongside the real books and see which parts help us recognise progress.