Data model¶
Data model¶
Logical stores¶
erDiagram
SECTIONS ||--o{ FIELDS : contains
ENTRIES ||--o{ ENTRY_VALUES : owns
FIELDS ||--o{ ENTRY_VALUES : defines
CATALOG_ITEMS ||--o{ EVENTS : classifies
EVENTS ||--o{ RESETS : may_trigger
PROFILES ||--o{ COUNTERS : owns
PROFILES }o--o{ EVENTS : concerns
| Store | Content | Key idea |
|---|---|---|
meta |
Runtime configuration, language, UI state, privacy | key/value metadata |
sections |
Visible sections of the daily check-in | order, label, Life Wheel axis |
fields |
Versioned field definitions | stable IDs and logicalId |
entries |
One daily record per date | sparse values map |
catalogItems |
People, sports, meals, triggers | reusable catalog objects |
events |
Repeatable events | social, exercise, self-care, meal, urge, trigger |
resets |
Counter start points and relapses | history instead of overwrite |
todos |
Tasks | state, priority, deadline |
inventoryEntries |
Recovery program-context reflections | retained for schema compatibility; hidden in General Audience |
chats, chatMessages |
Companion conversations | separate from tracking data |
Daily entry¶
{
"id": "2026-07-21",
"date": "2026-07-21",
"values": {
"sleep_quality": 4,
"stress": 4,
"day_management": 3
},
"createdAt": "...",
"updatedAt": "...",
"source": "app"
}
The values map is sparse. A missing key means unknown. This is semantically different from 0, false or "no".
Dynamic events¶
Repeatable things are not forced into the daily entry. Three social contacts on one day are three events, but they can reference the same person from catalogItems.
{
"id": "social-...",
"kind": "social",
"date": "2026-07-21",
"catalogItemId": "person-anna",
"connection": 4,
"note": "short conversation"
}
Runtime configuration¶
loadAppData() combines built-in default configuration with locally stored changes. This gives the UI a consistent object containing data, configuration and preferences.
For a fresh general-audience database, only the current sections and fields
are created. ensureConfiguration() adds missing current definitions in this
variant but does not inject absent legacy fields. Historical field definitions
that are actually present are still normalized and retained together with
their daily values. The same rule applies after a validated backup import.