Skip to content
Notion Arena
🏃
💼 Business & CRMProNative recipe

Sprint Tracker

Epics, stories and sprints with a velocity chart and a burndown-ready schema.

Version
v1.4.0
Updated
2026-09-29
Plan
Plus

The install plan

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.

25
requests
12
manual steps
1POST
/v1/pages

Create the “sprint-tracker” container page under the page you chose

2POST
/v1/databases

Create the “Epics” database with 6 base properties

3GET
/v1/databases/{epics_database_id}

Read back Epics to get its default data source id

4PATCH
/v1/data_sources/{epics_data_source_id}

Add 5 deferred properties to Epics: relations (with resolved data_source_ids), then the rollups and formulas that read them

5POST
/v1/databases

Create the “Stories” database with 12 base properties

6GET
/v1/databases/{stories_database_id}

Read back Stories to get its default data source id

7PATCH
/v1/data_sources/{stories_data_source_id}

Add 4 deferred properties to Stories: relations (with resolved data_source_ids), then the rollups and formulas that read them

8POST
/v1/databases

Create the “Sprints” database with 6 base properties

9GET
/v1/databases/{sprints_database_id}

Read back Sprints to get its default data source id

10PATCH
/v1/data_sources/{sprints_data_source_id}

Add 4 deferred properties to Sprints: relations (with resolved data_source_ids), then the rollups and formulas that read them

11POST
/v1/views

Create the “Sprint board” board view on stories

12POST
/v1/views

Create the “Backlog” list view on stories

13POST
/v1/views

Create the “Needs attention” table view on stories

14POST
/v1/views

Create the “Velocity by epic” chart view on epics

15POST
/v1/views

Create the “Sprint timeline” timeline view on sprints

16POST
/v1/views

Create the “Sprint dashboard” dashboard view (layout is read-only; widgets are added as further views with view_id)

17POST
/v1/pages

Seed 2 rows into Epics so the views are not empty on first open (one request per row; Notion has no bulk insert)

×2
18POST
/v1/pages

Seed 3 rows into Stories so the views are not empty on first open (one request per row; Notion has no bulk insert)

×3
19POST
/v1/pages

Seed 2 rows into Sprints so the views are not empty on first open (one request per row; Notion has no bulk insert)

×2
20POST
/v1/pages

Create the “Sprint rituals” page

21PATCH
/v1/blocks/{sprint_rituals_page_id}/children

Append 10 blocks of page body

“Sprint 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: Database template: “New story”; Automation: move to QA when In review clears; Widget views on the sprint dashboard.

Run it yourselfNotion-Version 2026-03-11
curl -X POST https://notionarena.vercel.app/api/install \
  -H 'content-type: application/json' \
  -d '{
    "component": "sprint-tracker",
    "mode": "plan"
  }'

# add "token" and "parentPageId" and switch to "mode": "api" to install for real

What gets created

The 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.

🏔️

Epics

ref: epics
1× title1× unique_id1× status2× select1× people1× relation2× rollup2× formula
Namen/a
Epic IDprefix EP
StatusBacklog → This quarter → In flight → Shipped +1
SquadPlatform · Product · Growth
Target quarter2026 Q3 · 2026 Q4 · 2027 Q1
Ownern/a
Stories→ stories (two-way)
Points totalsum(Stories.Points)
Points donesum(Done stories.Points)
% completeif(prop("Points total") == 0, 0, round(prop("Points done") / prop("Points total") * 100) / 100)
Progress barslice("██████████", 0, round(prop("% complete") * 10)) + " " + format(round(prop("% complete") * 100)) + "%"
🎟️

Stories

ref: stories
1× title1× unique_id1× status2× select2× relation1× people2× checkbox1× date1× rich_text1× created_time2× formula1× last_edited_time
Namen/a
Story IDprefix ST
StatusTriage → Ready → In progress → In review +3
TypeFeature · Bug · Chore · Spike
Points1 · 2 · 3 · 5 +2
Sprint→ sprints (two-way)
Epic→ epics
Assigneen/a
Blockedn/a
Carried overn/a
Done atn/a
Acceptance criterian/a
Createdn/a
In review forif(prop("Status") == "In review", dateBetween(now(), prop("Last edited"), "days"), 0)
Needs attentionifs(prop("Blocked"), "🚫 Blocked", prop("In review for") > 3, "🐌 Stuck in review", prop("Status") == "Triage" and prop("Carried over"), "↩️ Carried over", true, "")
Last editedn/a
🏃

Sprints

ref: sprints
1× title1× status2× date1× number1× rich_text1× relation2× rollup1× formula
Namen/a
StatusPlanned → Active → Closed
Startn/a
Endn/a
Capacity (points)number
Goaln/a
Stories→ stories
Committed pointscount_values(Stories.Points)
Days leftif(empty(prop("End")), 0, dateBetween(prop("End"), now(), "days"))
Velocitycount_values(Done stories.Points)

Views

Created through POST /v1/views, which shipped in March 2026 and is the reason provisioning a workspace from code finally works end to end.

Sprint boardboard

on stories

filter: {"property":"Status","group_does_not_equal":"Complete"}…

Backloglist

on stories

filter: {"property":"Sprint","relation":{"is_empty":true}}…

Needs attentiontable

on stories

filter: {"property":"Needs attention","string":{"does_not_equal":""}}…

Velocity by epicchart

on epics

Sprint timelinetimeline

on sprints

Sprint dashboarddashboard

on sprints

Documentation pages

Appended with real block types (headings, toggles, callouts, to-dos, column lists) in chunks of 100, the Append block children limit.

🔁Sprint rituals10 blocks
Monday: planning, 45 minutes
1.Read the sprint goal out loud. If nobody can, rewrite it before you pick work.
1.Pull from Backlog, not from Triage. Triage is not estimable by definition.
1.Stop at capacity. Carry-over stories count against capacity first.
Daily: 10 minutes
•Work the Needs attention view, not the board. The board tells you where things are; that view tells you where they are stuck.
•Anything In review for more than three days gets a name and a decision today.
Friday: review and retro, 40 minutes
•Compare Velocity to Capacity. Two consecutive sprints over capacity means the capacity number is wrong, not the team.
⚠️Carried-over stories get Carried over ticked before the sprint closes, or velocity lies to you next quarter.

The parts the API cannot do

Every 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.

Database template: “New story”

The API can apply a template when creating a page, but it cannot author the template's body. Build it once in the app and every new story inherits it.

  1. 1Stories → the ▾ next to New → + New template.
  2. 2Name it “New story”, set Status to Triage and Type to Feature as defaults.
  3. 3Body: an H2 “Context”, a to-do group “Acceptance criteria” with three empty items, an H2 “Notes”, and a callout “Definition of done”.
  4. 4Save. Optionally set it as the default for the Status = Triage filter.

Automation: move to QA when In review clears

Database automations have no public API surface. They are configured per-database in the Notion app under ••• → Automations.

  1. 1Stories → Automations → New automation.
  2. 2Trigger: Status changes to In review.
  3. 3Action: after 2 days, add a comment @mentioning the Assignee.
  4. 4Second automation: trigger when Blocked is checked → post to the squad's Slack channel.

Widget views on the sprint dashboard

Dashboard layout is read-only in the API. You can create the dashboard view itself, but each widget is a separate POST /v1/views with view_id set to the dashboard; the order they are created in becomes the layout.

  1. 1Create the dashboard view: POST /v1/views with type: "dashboard" and the Stories data source's database_id.
  2. 2Then, for each widget, POST /v1/views with view_id = the dashboard id and the widget's own data_source_id.
  3. 3Suggested order: a Number widget for Days left, a Board widget for the sprint, a Chart widget for velocity.
  4. 4Up to 12 widgets, 4 per row.

About this component

A two-database engineering system: Epics roll up story points and completion, Sprints hold capacity and dates. Includes a board grouped by status with a subtask toggle column, a velocity line chart, and the database template that every new story starts from.

What it does

  • Board configuration with a subtask toggle column: the API can set this
  • Chart view: line of points completed per sprint
  • Timeline view across sprints for roadmap conversations
  • Status groups mapped to Notion's native To begin / In progress / Done

Where people put it

↳Two-pizza product teams replacing Jira for lightweight tracking
↳Agency dev pods billing against sprints
↳Solo developers who still want velocity data

Pairs well with

All in Business & CRM
🧮

ROI Calculator

Sliders in, a payback chart out, for proposals and sales pages.

BusinessFreeWidgetv1.0.1
💵
New

Monthly Budget Planner

Compare monthly income against four editable expense buckets.

BusinessFreeWidgetv1.0.0
📦
New

Inventory Counter

Adjust a small item list with plus and minus stock controls.

BusinessFreeWidgetv1.0.0