CreatorTrack App Model , Collections + Custom View-Blocks¶
URL: https://mkdocs.justinsforge.com/memory/plans/creatortrack-app-model-collections-and-view-blocks-2026-06-19/
The architecture decision that resolves the recurring "is it a custom app or a database?" tension. Parent: [[creator-suite-vision-strategy-2026-06-17]], [[creatortrack-roadmap-2026-06-18]]. Settled with Justin 2026-06-19.
The principle (one line)¶
Every app is a database + a view. Precisely: every app decomposes into Data + View + (optional) Feed + (optional) Compute. CreatorTrack provides one primitive for each, so a new app is a configuration of those primitives, not new plumbing.
| Primitive | What it is | In CreatorTrack |
|---|---|---|
| Data | the rows: a collection of typed properties + relations | the collection engine (app.nodes + app.collection_props/_values/_views/_relations), already built |
| View | how a human sees the rows | collection_views + custom view-blocks (the new primitive) |
| Feed | where data comes from (integration/sync) | Forge pipelines (SimpleFIN for finance; same pattern for stocks/social) |
| Compute | what gets derived (rollups, categorization, ranking, ML) | rollups in-engine; custom React modules + AI for the hard parts |
Worked examples¶
- TickTick = tasks collection + list/board/calendar view. ~pure Data+View.
- RocketMoney = transactions+accounts collections + a Feed (bank sync) + Compute (categorization, recurring detection, alerts) + custom view.
- Stocks = holdings collection + a real-time market-data Feed + Compute (gains) + chart view.
- Instagram = posts/users/follows collections, but the product is Feed (uploads) + Compute (ranking algorithm) + media CDN. Data model is a DB; product is not "just a DB".
- Games = NOT a database+view (real-time simulation/render loop). The model's boundary.
"Just a database" is true of the data layer of nearly every tracking/business/creator app; it is false of the product when the value is mostly Feed (stocks) or Compute (IG ranking, games, video render). Those are the custom-module cases.
THE KEY DECISION: collections + custom view-blocks, NOT dedicated-table apps¶
Notion's power is one substrate: everything is a row in the same model, so relations/rollups/AI work across everything for free. Its limit is only ~6 built-in view renderers and you can't write a 7th.
CreatorTrack's edge = the same one-substrate data model + an open renderer set.
- A habit is a row in a Habits collection (props: icon, goal, cadence), NOT a row in a
separate app.habits table. So it can relate to a Project, be referenced in a doc, roll
up into a dashboard, and the AI reads it with the same query path as everything else.
- The polished UI (streaks, icons, animations) is a custom view-block: a bespoke React
renderer registered as a new collection_views.type beyond the 6 built-ins, bound to the
collection, embeddable as a block on any page. "Habits as a custom block" = a habit-tracker
view of the Habits collection.
- You don't choose between "database" and "custom app." A custom block IS a view of the
database. Full interconnection underneath, unlimited custom UI on top.
Consequence for existing schema¶
- The dedicated-table apps from the Flask prototype ,
app.habits/app.habit_logs(0009),app.time_entries(0010),app.meal_entries(0011) , are the WRONG fork: they bypass the collection model and become islands (no relations, AI must special-case each). Do NOT port them into CreatorTrack (React). Rebuild habits/food/time as collections + custom view-blocks. (Clean-slate rule: [[feedback_suite_clean_slate_rebuild]].) - Dedicated tables survive ONLY for genuine scale/special data: clips (video bytes on NVMe + pgvector embeddings) and finance (thousands of transactions). Even those expose a collection-style read contract so AI + relations stay uniform.
The new primitive to build (the "middle piece")¶
A custom view-block registry. Today collection_views.type is CHECK-constrained to
table/board/calendar/gallery/list/timeline. The registry lets a node render a collection
through an arbitrary registered React renderer (e.g. streak, habit-tracker, chart),
selectable as a view and droppable as a block. This is the reusable foundation every future
app (and eventually third-party apps , the app SDK) builds on. Building habits this way is
the first proof of the registry.
Build implication¶
First proof = Habits as a collection + a streak custom view-block (scope via
/feature-plan). Food, fitness, time-tracking then follow the same recipe. The Telegram
capture/read cutover ([[reference_forge_data_lifeos_spine]]) rides the same collection
contract so the bot, the UI, and AI all read one model.
[Claude Code]