Habit Heatmap Grid
GitHub-style contribution grid for up to six habits, with streaks.
Habits as database rows with streak formulas and a dashboard view.
Exactly what Notion Arena sends to Notion, in order. Notion's data-source model forces two passes: relations, rollups and the formulas that read them need data_source_ids that only exist once the databases do.
/v1/pagesCreate the “habit-os-native” container page under the page you chose
/v1/databasesCreate the “Habits” database with 8 base properties
/v1/databases/{habits_database_id}Read back Habits to get its default data source id
/v1/data_sources/{habits_data_source_id}Add 6 deferred properties to Habits: relations (with resolved data_source_ids), then the rollups and formulas that read them
/v1/databasesCreate the “Daily Logs” database with 6 base properties
/v1/databases/{logs_database_id}Read back Daily Logs to get its default data source id
/v1/data_sources/{logs_data_source_id}Add 4 deferred properties to Daily Logs: relations (with resolved data_source_ids), then the rollups and formulas that read them
/v1/viewsCreate the “Habit dashboard” dashboard view (layout is read-only; widgets are added as further views with view_id)
/v1/viewsCreate the “Active habits” gallery view on habits
/v1/viewsCreate the “Completion by habit” chart view on habits
/v1/viewsCreate the “Calendar” calendar view on logs
/v1/viewsCreate the “Today” table view on logs
/v1/viewsCreate the “Logs per week” chart view on logs
/v1/pagesSeed 3 rows into Habits so the views are not empty on first open (one request per row; Notion has no bulk insert)
/v1/pagesCreate the “Habit OS” page
/v1/blocks/{habit_os_page_id}/childrenAppend 11 blocks of page body
“Habit dashboard” is created empty. Dashboard configuration is read-only in the API: each widget is its own POST /v1/views with view_id set to the dashboard. See the manual steps.
3 steps cannot be scripted: Button: “Log today”; Recurring template: daily log seeder; Widget views on the habit dashboard.
curl -X POST https://notionarena.vercel.app/api/install \
-H 'content-type: application/json' \
-d '{
"component": "habit-os-native",
"mode": "plan"
}'
# add "token" and "parentPageId" and switch to "mode": "api" to install for realThe real property schemas, not a description of them. Every formula below is a Notion Formula 2.0 expression you can paste into a property by hand if you would rather not use the API at all.
ref: habitsn/an/aDaily · Weekdays · 3× per week · Weeklynumbern/an/an/a→ logs (two-way)count(Recent logs.Completed)checked(Logs.Completed)count_values(Logs.Name)if(prop("Total logs") == 0, 0, round(prop("Completed count") / prop("Total logs") * 100))numberifs(not(prop("Active")), "⏸ Paused", prop("All-time rate") >= 80, "🔥 Strong", prop("All-time rate") >= 50, "🌱 Building", true, "🧊 Fragile")ref: logsn/an/a→ habitsn/anumbern/aformatDate(prop("Date"), "ddd")dateBetween(prop("Date"), now(), "days") == 0formatDate(prop("Date"), "wo")n/aCreated through POST /v1/views, which shipped in March 2026 and is the reason provisioning a workspace from code finally works end to end.
on habits
on habits
filter: {"property":"Active","checkbox":{"equals":true}}…
on habits
on logs
filter: {"property":"Completed","checkbox":{"equals":true}}…
on logs
filter: {"property":"Is today","checkbox":{"equals":true}}…
on logs
Appended with real block types (headings, toggles, callouts, to-dos, column lists) in chunks of 100, the Append block children limit.
round(prop("Completed count") / prop("Total logs") * 100)formatDate(prop("Date"), "ddd")dateBetween(prop("Date"), now(), "days") == 0Every recipe ships with its manual steps written out, because pretending the API covers everything is how people end up with a half-built workspace. These are real Notion limitations, quoted from the API reference.
Button properties are response-only in the Notion API: the schema is returned on read, but the API ignores button settings on write and cannot create a button or configure its actions.
Recurring database templates (daily/weekly/monthly) are configured in the app on the template's ••• menu; the API can create pages from a template but cannot schedule recurrence.
Dashboard configuration is read-only. Create the dashboard, then add each widget as its own view with view_id pointing at it.
The data-backed counterpart to the Habit Heatmap widget. A Habits database and a Logs database, with formulas that compute current streak, longest streak and 30-day completion rate directly from your rows, so it syncs across devices and teammates, unlike any widget.
GitHub-style contribution grid for up to six habits, with streaks.
A one-tap daily drink counter with a goal ring and undo.
Log how you feel in one tap and see the month as a calendar heatmap.