Email
← Projects

Hive, a Classroom Curation Platform

A classroom platform for publishing collections of links, images, and video, migrated from JSX to TypeScript during weekly releases.

The source code is client-owned and is not public.

What it is

A classroom content-curation platform: curators sign in, pull items into collections, tag and order them, and publish the result to a public-facing view. React front end, AdonisJS API, PostgreSQL underneath, deployed and used in production.

The application was already live when I began the TypeScript migration. New features still had to ship while I converted the existing modules.

TypeScript migration

The starting point was a JSX codebase with no type coverage and an active feature roadmap. The approach:

  1. Enable allowJs with checkJs: false so JavaScript and TypeScript modules can coexist.
  2. Convert utility modules first, keeping each change small enough to review and deploy.
  3. Define Item, Collection, Tag, and Curator before converting the components that use them.
  4. Keep strict settings enabled on converted modules.

The migration exposed API fields that could be null but were rendered unconditionally by the UI. I added checks at those call sites.

Rendering and query latency

Feedback often described the symptom without identifying the cause. “The list feels slow” meant a rendering problem on one screen and a query problem on another. I had to reproduce each report before deciding where to fix it.

I also left instrumentation too late. Without request-latency measurements, performance conversations were harder to resolve. I would add that visibility earlier on the next project.

Design decisions

  • Incremental TypeScript migration, file-by-file, with `allowJs` on

    RejectedA big-bang rewrite on a long-lived branch

    Weekly releases continued during the migration. With `allowJs: true`, typed and untyped modules could coexist, so I could deploy each converted module and pause the migration when feature work took priority.

  • AdonisJS over a bare Express setup

    RejectedExpress with hand-assembled middleware, validation, and ORM

    Adonis provided validation, migrations, and an ORM within one framework. That reduced integration work for a solo developer on a client deadline, at the cost of a smaller ecosystem than Express.

  • PostgreSQL with explicit migrations from day one

    RejectedA document store, or an ORM with auto-syncing schema

    Items, collections, tags, and curators form a relational model. Foreign keys enforce those relationships, and explicit migrations give schema changes a reviewable history.

What I’d do differently

  • Turn on `strict` mode at the very start with the whole codebase in `allowJs`, rather than enabling strictness per-module. Ratcheting strictness later meant revisiting files I had already converted once.
  • Write the seed script in week one. I tested against hand-made data far longer than I should have, which hid at least one ordering bug that only appeared with realistic volume.
  • Instrument earlier. I had no request-latency visibility until late, so performance conversations with the client were qualitative when they should have been numeric.