{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"sprint-tracker","type":"registry:block","title":"Sprint Tracker","description":"Epics, stories and sprints with a velocity chart and a burndown-ready schema.","author":"Notion Arena","categories":["business"],"tags":["native","pro","agile","sprint","engineering","velocity","scrum"],"meta":{"kind":"native","tier":"pro","version":"1.4.0","updatedAt":"2026-09-29","notionPlan":"Plus","emoji":"🏃","delivery":["api","duplicate","guide"],"capabilities":{"interactive":false,"offlineSafe":true,"persistsLocally":false,"writesToNotion":true,"needsNetwork":false},"recipe":"sprint-tracker","installUrl":"https://notionarena.vercel.app/api/install"},"files":[{"path":"recipes/sprint-tracker.json","type":"registry:file","target":"notion/recipes/sprint-tracker.json","content":"{\n  \"$schema\": \"https://notionarena.vercel.app/r/schema.json\",\n  \"notionVersion\": \"2026-03-11\",\n  \"id\": \"sprint-tracker\",\n  \"summary\": \"Epics and Stories with a two-way relation, points rollups, a sprint board with a subtask toggle column, and a velocity line chart.\",\n  \"databases\": [\n    {\n      \"ref\": \"epics\",\n      \"title\": \"Epics\",\n      \"icon\": \"🏔️\",\n      \"properties\": {\n        \"Name\": {\n          \"title\": {}\n        },\n        \"Epic ID\": {\n          \"unique_id\": {\n            \"prefix\": \"EP\"\n          }\n        },\n        \"Status\": {\n          \"status\": {\n            \"options\": [\n              {\n                \"name\": \"Backlog\",\n                \"color\": \"gray\",\n                \"group\": \"To-do\"\n              },\n              {\n                \"name\": \"This quarter\",\n                \"color\": \"blue\",\n                \"group\": \"To-do\"\n              },\n              {\n                \"name\": \"In flight\",\n                \"color\": \"yellow\",\n                \"group\": \"In progress\"\n              },\n              {\n                \"name\": \"Shipped\",\n                \"color\": \"green\",\n                \"group\": \"Complete\"\n              },\n              {\n                \"name\": \"Cut\",\n                \"color\": \"red\",\n                \"group\": \"Complete\"\n              }\n            ]\n          }\n        },\n        \"Squad\": {\n          \"select\": {\n            \"options\": [\n              {\n                \"name\": \"Platform\",\n                \"color\": \"blue\"\n              },\n              {\n                \"name\": \"Product\",\n                \"color\": \"purple\"\n              },\n              {\n                \"name\": \"Growth\",\n                \"color\": \"green\"\n              }\n            ]\n          }\n        },\n        \"Target quarter\": {\n          \"select\": {\n            \"options\": [\n              {\n                \"name\": \"2026 Q3\",\n                \"color\": \"gray\"\n              },\n              {\n                \"name\": \"2026 Q4\",\n                \"color\": \"blue\"\n              },\n              {\n                \"name\": \"2027 Q1\",\n                \"color\": \"purple\"\n              }\n            ]\n          }\n        },\n        \"Owner\": {\n          \"people\": {}\n        },\n        \"Stories\": {\n          \"relation\": {\n            \"type\": \"dual_property\",\n            \"dual_property\": {\n              \"synced_property_name\": \"Epic\"\n            }\n          },\n          \"__relationRef\": \"stories\"\n        },\n        \"Points total\": {\n          \"rollup\": {\n            \"relation_property_name\": \"Stories\",\n            \"rollup_property_name\": \"Points\",\n            \"function\": \"sum\"\n          }\n        },\n        \"Points done\": {\n          \"rollup\": {\n            \"relation_property_name\": \"Done stories\",\n            \"rollup_property_name\": \"Points\",\n            \"function\": \"sum\"\n          }\n        },\n        \"% complete\": {\n          \"formula\": {\n            \"expression\": \"if(prop(\\\"Points total\\\") == 0, 0, round(prop(\\\"Points done\\\") / prop(\\\"Points total\\\") * 100) / 100)\"\n          }\n        },\n        \"Progress bar\": {\n          \"formula\": {\n            \"expression\": \"slice(\\\"██████████\\\", 0, round(prop(\\\"% complete\\\") * 10)) + \\\" \\\" + format(round(prop(\\\"% complete\\\") * 100)) + \\\"%\\\"\"\n          }\n        }\n      },\n      \"seed\": [\n        {\n          \"name\": \"Component registry v2\",\n          \"props\": {\n            \"Status\": \"In flight\",\n            \"Squad\": \"Platform\",\n            \"Target quarter\": \"2026 Q4\"\n          }\n        },\n        {\n          \"name\": \"Self-serve onboarding\",\n          \"props\": {\n            \"Status\": \"This quarter\",\n            \"Squad\": \"Growth\",\n            \"Target quarter\": \"2026 Q4\"\n          }\n        }\n      ]\n    },\n    {\n      \"ref\": \"stories\",\n      \"title\": \"Stories\",\n      \"icon\": \"🎟️\",\n      \"properties\": {\n        \"Name\": {\n          \"title\": {}\n        },\n        \"Story ID\": {\n          \"unique_id\": {\n            \"prefix\": \"ST\"\n          }\n        },\n        \"Status\": {\n          \"status\": {\n            \"options\": [\n              {\n                \"name\": \"Triage\",\n                \"color\": \"gray\",\n                \"group\": \"To-do\"\n              },\n              {\n                \"name\": \"Ready\",\n                \"color\": \"blue\",\n                \"group\": \"To-do\"\n              },\n              {\n                \"name\": \"In progress\",\n                \"color\": \"yellow\",\n                \"group\": \"In progress\"\n              },\n              {\n                \"name\": \"In review\",\n                \"color\": \"purple\",\n                \"group\": \"In progress\"\n              },\n              {\n                \"name\": \"QA\",\n                \"color\": \"orange\",\n                \"group\": \"In progress\"\n              },\n              {\n                \"name\": \"Done\",\n                \"color\": \"green\",\n                \"group\": \"Complete\"\n              },\n              {\n                \"name\": \"Won't do\",\n                \"color\": \"red\",\n                \"group\": \"Complete\"\n              }\n            ]\n          }\n        },\n        \"Type\": {\n          \"select\": {\n            \"options\": [\n              {\n                \"name\": \"Feature\",\n                \"color\": \"blue\"\n              },\n              {\n                \"name\": \"Bug\",\n                \"color\": \"red\"\n              },\n              {\n                \"name\": \"Chore\",\n                \"color\": \"gray\"\n              },\n              {\n                \"name\": \"Spike\",\n                \"color\": \"purple\"\n              }\n            ]\n          }\n        },\n        \"Points\": {\n          \"select\": {\n            \"options\": [\n              {\n                \"name\": \"1\",\n                \"color\": \"gray\"\n              },\n              {\n                \"name\": \"2\",\n                \"color\": \"gray\"\n              },\n              {\n                \"name\": \"3\",\n                \"color\": \"blue\"\n              },\n              {\n                \"name\": \"5\",\n                \"color\": \"blue\"\n              },\n              {\n                \"name\": \"8\",\n                \"color\": \"yellow\"\n              },\n              {\n                \"name\": \"13\",\n                \"color\": \"red\"\n              }\n            ]\n          }\n        },\n        \"Sprint\": {\n          \"relation\": {\n            \"type\": \"dual_property\",\n            \"dual_property\": {\n              \"synced_property_name\": \"Stories\"\n            }\n          },\n          \"__relationRef\": \"sprints\"\n        },\n        \"Epic\": {\n          \"relation\": {\n            \"type\": \"single_property\",\n            \"single_property\": {}\n          },\n          \"__relationRef\": \"epics\"\n        },\n        \"Assignee\": {\n          \"people\": {}\n        },\n        \"Blocked\": {\n          \"checkbox\": {}\n        },\n        \"Carried over\": {\n          \"checkbox\": {}\n        },\n        \"Done at\": {\n          \"date\": {}\n        },\n        \"Acceptance criteria\": {\n          \"rich_text\": {}\n        },\n        \"Created\": {\n          \"created_time\": {}\n        },\n        \"In review for\": {\n          \"formula\": {\n            \"expression\": \"if(prop(\\\"Status\\\") == \\\"In review\\\", dateBetween(now(), prop(\\\"Last edited\\\"), \\\"days\\\"), 0)\"\n          }\n        },\n        \"Needs attention\": {\n          \"formula\": {\n            \"expression\": \"ifs(prop(\\\"Blocked\\\"), \\\"🚫 Blocked\\\", prop(\\\"In review for\\\") > 3, \\\"🐌 Stuck in review\\\", prop(\\\"Status\\\") == \\\"Triage\\\" and prop(\\\"Carried over\\\"), \\\"↩️ Carried over\\\", true, \\\"\\\")\"\n          }\n        },\n        \"Last edited\": {\n          \"last_edited_time\": {}\n        }\n      },\n      \"seed\": [\n        {\n          \"name\": \"Registry JSON endpoints\",\n          \"props\": {\n            \"Status\": \"In progress\",\n            \"Type\": \"Feature\",\n            \"Points\": \"5\"\n          }\n        },\n        {\n          \"name\": \"Widget sandbox hardening\",\n          \"props\": {\n            \"Status\": \"In review\",\n            \"Type\": \"Chore\",\n            \"Points\": \"3\"\n          }\n        },\n        {\n          \"name\": \"Embed height jumps on resize\",\n          \"props\": {\n            \"Status\": \"Triage\",\n            \"Type\": \"Bug\",\n            \"Points\": \"2\"\n          }\n        }\n      ]\n    },\n    {\n      \"ref\": \"sprints\",\n      \"title\": \"Sprints\",\n      \"icon\": \"🏃\",\n      \"properties\": {\n        \"Name\": {\n          \"title\": {}\n        },\n        \"Status\": {\n          \"status\": {\n            \"options\": [\n              {\n                \"name\": \"Planned\",\n                \"color\": \"gray\",\n                \"group\": \"To-do\"\n              },\n              {\n                \"name\": \"Active\",\n                \"color\": \"yellow\",\n                \"group\": \"In progress\"\n              },\n              {\n                \"name\": \"Closed\",\n                \"color\": \"green\",\n                \"group\": \"Complete\"\n              }\n            ]\n          }\n        },\n        \"Start\": {\n          \"date\": {}\n        },\n        \"End\": {\n          \"date\": {}\n        },\n        \"Capacity (points)\": {\n          \"number\": {\n            \"format\": \"number\"\n          }\n        },\n        \"Goal\": {\n          \"rich_text\": {}\n        },\n        \"Stories\": {\n          \"relation\": {\n            \"type\": \"single_property\",\n            \"single_property\": {}\n          },\n          \"__relationRef\": \"stories\"\n        },\n        \"Committed points\": {\n          \"rollup\": {\n            \"relation_property_name\": \"Stories\",\n            \"rollup_property_name\": \"Points\",\n            \"function\": \"count_values\"\n          }\n        },\n        \"Days left\": {\n          \"formula\": {\n            \"expression\": \"if(empty(prop(\\\"End\\\")), 0, dateBetween(prop(\\\"End\\\"), now(), \\\"days\\\"))\"\n          }\n        },\n        \"Velocity\": {\n          \"rollup\": {\n            \"relation_property_name\": \"Done stories\",\n            \"rollup_property_name\": \"Points\",\n            \"function\": \"count_values\"\n          }\n        }\n      },\n      \"seed\": [\n        {\n          \"name\": \"Sprint 24: registry\",\n          \"props\": {\n            \"Status\": \"Active\",\n            \"Capacity (points)\": 34,\n            \"Goal\": \"Ship the public registry endpoints and harden the widget sandbox.\"\n          }\n        },\n        {\n          \"name\": \"Sprint 25: install flow\",\n          \"props\": {\n            \"Status\": \"Planned\",\n            \"Capacity (points)\": 34\n          }\n        }\n      ]\n    }\n  ],\n  \"views\": [\n    {\n      \"on\": \"stories\",\n      \"name\": \"Sprint board\",\n      \"type\": \"board\",\n      \"configuration\": {\n        \"type\": \"board\",\n        \"group_by\": {\n          \"type\": \"status\",\n          \"property_name\": \"Status\",\n          \"group_by\": \"option\",\n          \"sort\": {\n            \"type\": \"manual\"\n          }\n        },\n        \"subtasks\": {\n          \"property_name\": \"Epic\",\n          \"toggle_column_name\": \"Blocked\"\n        },\n        \"card_layout\": \"comfortable\"\n      },\n      \"filter\": {\n        \"property\": \"Status\",\n        \"group_does_not_equal\": \"Complete\"\n      }\n    },\n    {\n      \"on\": \"stories\",\n      \"name\": \"Backlog\",\n      \"type\": \"list\",\n      \"filter\": {\n        \"property\": \"Sprint\",\n        \"relation\": {\n          \"is_empty\": true\n        }\n      },\n      \"sorts\": [\n        {\n          \"property\": \"Points\",\n          \"direction\": \"ascending\"\n        }\n      ]\n    },\n    {\n      \"on\": \"stories\",\n      \"name\": \"Needs attention\",\n      \"type\": \"table\",\n      \"filter\": {\n        \"property\": \"Needs attention\",\n        \"string\": {\n          \"does_not_equal\": \"\"\n        }\n      }\n    },\n    {\n      \"on\": \"epics\",\n      \"name\": \"Velocity by epic\",\n      \"type\": \"chart\",\n      \"configuration\": {\n        \"type\": \"chart\",\n        \"chart_type\": \"bar\",\n        \"x_axis\": {\n          \"type\": \"select\",\n          \"property_name\": \"Squad\",\n          \"sort\": {\n            \"type\": \"manual\"\n          }\n        },\n        \"y_axis\": {\n          \"aggregator\": \"sum\",\n          \"property_name\": \"Points done\"\n        },\n        \"color_theme\": \"purple\",\n        \"show_data_labels\": true,\n        \"height\": \"medium\"\n      }\n    },\n    {\n      \"on\": \"sprints\",\n      \"name\": \"Sprint timeline\",\n      \"type\": \"timeline\",\n      \"configuration\": {\n        \"type\": \"timeline\"\n      }\n    },\n    {\n      \"on\": \"sprints\",\n      \"name\": \"Sprint dashboard\",\n      \"type\": \"dashboard\"\n    }\n  ],\n  \"pages\": [\n    {\n      \"title\": \"Sprint rituals\",\n      \"icon\": \"🔁\",\n      \"blocks\": [\n        {\n          \"object\": \"block\",\n          \"type\": \"heading_2\",\n          \"heading_2\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Monday: planning, 45 minutes\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\",\n            \"is_toggleable\": false\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"numbered_list_item\",\n          \"numbered_list_item\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Read the sprint goal out loud. If nobody can, rewrite it before you pick work.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\"\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"numbered_list_item\",\n          \"numbered_list_item\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Pull from Backlog, not from Triage. Triage is not estimable by definition.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\"\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"numbered_list_item\",\n          \"numbered_list_item\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Stop at capacity. Carry-over stories count against capacity first.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\"\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"heading_2\",\n          \"heading_2\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Daily: 10 minutes\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\",\n            \"is_toggleable\": false\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"bulleted_list_item\",\n          \"bulleted_list_item\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Work the Needs attention view, not the board. The board tells you where things are; that view tells you where they are stuck.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\"\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"bulleted_list_item\",\n          \"bulleted_list_item\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Anything In review for more than three days gets a name and a decision today.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\"\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"heading_2\",\n          \"heading_2\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Friday: review and retro, 40 minutes\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\",\n            \"is_toggleable\": false\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"bulleted_list_item\",\n          \"bulleted_list_item\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Compare Velocity to Capacity. Two consecutive sprints over capacity means the capacity number is wrong, not the team.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"color\": \"default\"\n          }\n        },\n        {\n          \"object\": \"block\",\n          \"type\": \"callout\",\n          \"callout\": {\n            \"rich_text\": [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Carried-over stories get \",\n                  \"link\": null\n                }\n              },\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Carried over\",\n                  \"link\": null\n                },\n                \"annotations\": {\n                  \"code\": true\n                }\n              },\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \" ticked before the sprint closes, or velocity lies to you next quarter.\",\n                  \"link\": null\n                }\n              }\n            ],\n            \"icon\": {\n              \"type\": \"emoji\",\n              \"emoji\": \"⚠️\"\n            },\n            \"color\": \"yellow_background\"\n          }\n        }\n      ]\n    }\n  ]\n}"},{"path":"recipes/sprint-tracker.manual.md","type":"registry:file","target":"notion/recipes/sprint-tracker.manual.md","content":"## Database template: “New story”\n\n**Why this cannot be scripted:** 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.\n\n1. Stories → the ▾ next to New → + New template.\n2. Name it “New story”, set Status to Triage and Type to Feature as defaults.\n3. Body: an H2 “Context”, a to-do group “Acceptance criteria” with three empty items, an H2 “Notes”, and a callout “Definition of done”.\n4. Save. Optionally set it as the default for the Status = Triage filter.\n\n## Automation: move to QA when In review clears\n\n**Why this cannot be scripted:** Database automations have no public API surface. They are configured per-database in the Notion app under ••• → Automations.\n\n1. Stories → Automations → New automation.\n2. Trigger: Status changes to In review.\n3. Action: after 2 days, add a comment @mentioning the Assignee.\n4. Second automation: trigger when Blocked is checked → post to the squad's Slack channel.\n\n## Widget views on the sprint dashboard\n\n**Why this cannot be scripted:** 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.\n\n1. Create the dashboard view: POST /v1/views with type: \"dashboard\" and the Stories data source's database_id.\n2. Then, for each widget, POST /v1/views with view_id = the dashboard id and the widget's own data_source_id.\n3. Suggested order: a Number widget for Days left, a Board widget for the sprint, a Chart widget for velocity.\n4. Up to 12 widgets, 4 per row.\n"}]}