A single config file turns the same app into PetCare, ChildCare, AutoCare, or BikeCare.
serviceConfig.ts decides terminology, feature flags, and theme, and the whole product re-skins itself around a new vertical. Build the booking-and-billing engine once, ship it as four brands.“Booking + customers + payments” is the same software whether the thing being cared for is a pet, a child, a car, or a bike. Rebuilding it per vertical is wasted work; forking it per client is a maintenance trap where every bug fix has to be applied N times.
The bet: express everything that differs between verticals as data, and keep the engine identical. One bug fix, four products improved.
The architecture is the config boundary. Anything vertical-specific — labels, enabled features, colours — is data; everything else is shared engine code that never knows which brand it is running as.
Every vertical difference funnels through serviceConfig.ts. Components read terminology and flags from it rather than hard-coding “pet” or “child” — so a new vertical is a new config, not a new branch.
Each brand is a set of CSS-variable tokens, so re-skinning is runtime, not a separate build. The same lesson powers this portfolio's twelve palettes.
BikeCare might not need vaccination reminders; ChildCare does. Flags in the config switch whole features on and off so the codebase stays singular instead of splintering per client.
Abstract too little and every vertical needs code changes; abstract too much and the config becomes a second programming language. Drawing that line is the entire design problem.
If a component asks the config for a label that a vertical forgot to define, that should be a compile error, not a blank string in production. Keeping the terminology map fully typed is what makes the pattern safe.
Every new toggle is tempting to add to the config. Without discipline it balloons into an unreadable mega-object — so the bar for “does this truly differ per vertical?” has to stay high.
“Write the engine once, describe the product as data. The hard part is deciding what counts as data.”— Parm, on CareKit