BuildBot

One Engine, Many Brands

Progress modeling & packaging

Lesson 3 of 3

What you'll learn

  • Store the minimum durable fact and derive the rest
  • Design progress so it can move from local to account-based later
  • Turn a custom build into a repeatable client package

Store facts, derive dashboards

The smallest durable fact about learning is which lessons are complete. Store that set of slugs — nothing else. Everything a dashboard shows (percent done, current streak, next lesson) is derived from it.

const completed = new Set(["intro", "tokens"]);
const percent = Math.round((completed.size / totalLessons) * 100);

Store slugs, not rendered numbers. A stable identifier set survives a redesign and migrates cleanly: the same shape that lives in localStorage today becomes a database row keyed by user later, with no change to how the dashboard computes.

Package for repeatable delivery

A product is resellable when delivery is a kit, not a one-off. Each client launch combines the same engine with tenant-specific inputs:

  • the shared engine (this app),
  • a brand (tokens + copy),
  • curated content,
  • deployment config (domain, env),
  • a launch checklist (auth, data sync, analytics, monitoring).

Demo-ready ≠ production-ready

A branded demo is easy; a paying tenant needs auth, durable progress sync, content review, analytics, and monitoring. Keep that checklist explicit so "looks done" never gets mistaken for "is done."

The challenge derives a tenant's dashboard from stored facts and a packaging checklist. Run it.

Derive progress + launch readiness

Progress is computed from completed slugs; readiness is computed from the checklist. Run it.

Loading editor…

That's the white-label trio: brand as data, look as tokens, delivery as a repeatable package. You can now turn one well-built app into a product you sell many times.

Knowledge check

Why store the set of completed lesson slugs rather than the computed percent done?

Saved on this device. Sign in to sync your progress everywhere.