A module is a ready-made set of trackables for one area of life: Sleep, Emotions, Food & drink, Strength. Taking one in setup or later in Settings makes its trackables, any catalog they log from, and the tags they are filed under, so a new profile starts with a working arrangement rather than an empty list. The demo profiles are built from the same modules, so a beginner’s Sleep and Chad’s Sleep are the same shape.

Setup runs the chosen modules one after another, with no transaction around them. A run that fails part-way keeps the modules it finished, joins them to Every day, takes away what the failing module had made so far (it records its install last, so nothing else would mark it), and says which were set up and which failed. Setting up again skips a module already installed, so it finishes the rest rather than making a second copy (runOnboarding in apps/renderer/src/onboarding/setup.ts).

A module is a configuration of the general primitives and nothing more. What it makes is ordinary trackables, catalogs and derived trackables, which a person could have made by hand and can change like any other. The module functions are in packages/core/src/modules.ts (and sleep-module.ts), written over the repository seam with no React and no Node, so they run in the app’s setup and in the seed tooling alike.

The first-party modules

ModuleMakesFiled underFollows updates
Emotionsthe Emotion catalog, Emotions, Pleasantness, Stress (Emotions)Signalsyes
EnergyEnergy, a four-step scale from Drained to ChargedSignalsyes
SymptomsSymptoms, a remembered symptom with a severitySignalsyes
SleepSleep, and by preset Main sleep, Other sleep, Napped, Total sleep, Bedtime, Waketime (Sleep)Restyes
Daily habitsMeditate and Read as intervals, Journal, and the Books catalog (Reading a Book)Habitsyes
WeightWeightSignalsyes
WaterWaterNutritionyes
FocusFocusSignalsyes
Cardiothe Activity catalog, Cardio, ExercisedFitnessyes
HygieneBrush teeth, Shower, and a Morning routineHygieneyes
WeatherWeather, logged for you (Weather)Externalyes
DisruptionsDisruption, whose entries put days on hold—yes
Food & drinkthe Food catalog with its drinks, Diet, Meal, Daily Calories, and Daily Caffeine or Daily Alcohol where the run asks for them (setup makes Daily Caffeine; Chad’s seed both)Nutritionyes
Strengththe Exercise catalog, Set, Daily Volume, WorkoutFitnessyes

Rest days, a derived yes or no for a day with no Set logged, is made for Strength by the demo seed and filed under Rest. A module that reads another’s trackable is handed it by id, never found by its name.

The first-party tags

Modules file what they make under a small set of tags (FIRST_PARTY_FOLDERS), each made on demand, so taking Energy alone gives Signals and no empty Fitness:

  • Rest, Nutrition, Fitness, Habits, Hygiene: things you do.
  • Signals: things you observe. The split is the one a visualization of several trackables exists to explore, how what you do affects what you observe. It is not stored anywhere beyond the tag itself.
  • External: what is not about you at all, Weather first.

The names avoid two traps. Signals rather than Health, because Health always invites the question of why Fitness is not inside it. Fitness rather than Exercise, because the Exercise catalog owns that word. Hygiene is kept apart from Habits because they mean different things on a bad day: brushing your teeth is baseline, meditating is elective, and “Hygiene 2/2, Habits 0/3” says more than “2 of 5”.

A module files into a tag by its name (fileUnder), so two modules run in either order find the same one, and running a module again files into what is there; Daily habits files its habits into Habits the same way. A tag a module files into is no role of the module’s: it is the person’s, made by hand or not. Tags are ordinary and can be renamed; a module run after a first-party tag is renamed makes a second one under the first-party name.

The install record

Each run of a module writes a module_install row: which module, its preset, and the answers its setup questions were given. Each trackable it made is stamped with that install (install_id) and its role in it (module_role), written only by the install repository so a form save cannot clear them. Installs sync ahead of trackables. Tags shared between modules belong to no install.

Setup questions and presets. A module can ask questions in setup, under its card, and can offer presets: choices of which derived trackables exist, never of how anything is stored. Sleep is the one module with presets. Settings, Modules lists what setup made, switches a preset after showing what it would add, remove and keep, and offers the modules not yet added, each with what it makes, to add one at a time. Sleep’s names come from core (sleepRoleName, sleepMakes), the same names its trackables are made with, so setup’s line follows the preset picked and a switch names every role it adds.

Every setup question has a default, so setup never becomes a questionnaire. A choice that affects one trackable lives on that trackable and is changed in its own form, as Main sleep’s rule is; the setup answer only sets where it starts. A change that spans several trackables, or adds or removes one, goes through the module. Since derived trackables are worked out when read, a switch recomputes every past day and migrates nothing. Two ways of reading that would need differently shaped logged data are two modules, not two presets.

Following a module

A module’s trackables and catalogs follow it: when a newer version of the module would make one differently, it takes the change, a trackable until it is made yours.

  • What the module makes now is read by running the module against repositories that only remember what they are given (moduleDefinitions and moduleCatalogDefinitions in packages/core/src/module-follow.ts), with ids mapped to the install’s: its trackables’ and its catalogs’, so Diet’s Food field names the profile’s own Food catalog. A catalog’s items are not made again: what a module makes of a catalog is its settings. A setting that still names something only the re-run made, such as the tag a trackable is filed under, is never written. A newer module is read from its own code, so following reads no version number; the install’s version column is written as 1 and nothing reads it.

  • The snapshot. Each following trackable keeps the definition it last took (module_snapshot). A trackable seen for the first time takes the module’s definition as its snapshot and changes nothing.

  • Taking an update. When the app opens, a follower whose module now makes it differently takes each setting the module changed and it has not, field by field and setting by setting. It takes nothing that would change how its entries read: a field’s kind, an option entries hold, or which end dates an interval are left as they are. Options are taken only where the module relabelled or added, never where it took a code away.

  • Made yours. A change to a following trackable that alters how its entries read is an unsafe change (Trackable Authoring Flow); saving one asks first and says that the trackable becomes yours. It is marked made_yours_at, still knows its module, and its module’s updates stop reaching it. Its edit page’s Module section says which module made it, whether it follows, and for one made yours, whether the module has changed since.

  • Reattach puts the module’s fields, options and formula back over the trackable’s, and keeps its name, colour, description, visualizations and cadence, since changing those never made it yours. A field it added is hidden with its values kept. The question lists what is given up.

  • A catalog follows as a trackable does, by role (module_role and module_snapshot on the catalog, stamped by recordInstall): its name, dataset, source and colour, and its fields setting by setting, each where the catalog still has it as the module had it (catalogUpdate). Never its base unit, which changes what every item’s numbers mean, nor a change to how its values read; a field the person added is kept, and a change its items refuse (a Category value they still hold) waits. A catalog seen for the first time takes only what it lacks, a field or a field’s setting, and loses nothing, so a catalog made before its module learned something learns it. One installed before catalogs were stamped is found by its dataset, else its name, and stamped (useModuleFollow). A catalog is never made yours.

Rest days, which reads another module’s trackable, is not followed: its trackable says where it came from, without updates or Reattach.

Sleep · Emotions · Reading a Book · Trackable Authoring Flow · Exercise & Strength · Diet and Nutrition