Bootstrap notion
An AI second brain with an action layer — Notion + Claude.
npx -y skills add Kisslotina/Steward --skill bootstrap-notionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Creates the full Steward Notion structure from scratch — all bases with fields, relations, Area rows, filtered views, emojis — and writes the per-user base registry. Use once on first-time setup / fresh install, or when the user asks to bootstrap, initialize, or recreate the Notion bases. Requires the Notion connector with permission to create databases and pages in a chosen parent page.
SKILL.md
10.7 KB, as published. Nobody here has run it
Bootstrap Notion
One-time setup. Creates every base the system needs, wired with relations, then saves a registry of data-source IDs.
Source of truth. The field/value list below is an executable copy for running the bootstrap. Canon for structure is
docs/data-model.md; canon for exact names & select values is.claude/rules/conventions.md(Inbox.Typeintaxonomy.md). On any disagreement those win and this list is corrected to match — keep them in sync.
Prerequisites
- Notion connector connected, able to create databases/pages.
- Ask the user where to create everything, and create the Steward page directly there:
- their Private space (cleanest — pass no parent / a private page), or
- an existing teamspace/page they name.
- Do NOT create a new teamspace. Notion auto-adds a default "Teamspace Home" page to every new teamspace, which we don't want. Always place Steward under an existing location.
- Create the Steward container page, the 10 databases, and the Today page inside it. Do NOT create any other pages, sections, or sub-pages.
Order (relations need their targets to exist first)
Create each as a database under the parent; put the emoji in the title (e.g. 📥 Inbox).
- 📥 Inbox —
Note(title),Status(select: New, Sorted),Type(select: task, reminder, reference, goal, idea, event, review, expense, unsure),Target(text). Date = created time. - 🔁 Areas DB —
Area(title),Notes(text). Add rows, each with an emoji in the title text (emoji + space + name): 💼 Career, 🩺 Health, 🏃 Sport, 💰 Money, 👨👩👧 Family, ✍️ Content, 📦 Other. - 🎯 Goals —
Goal(title),Horizon(select: Yearly, Short-term),Target date(date),Status(select: Not started, In progress, Done),Notes(text),AreaRELATION → Areas DB (two-way "Goals"). - 🚀 Projects —
Project(title),Status(select: Backlog, Active, On hold, Done),Deadline(date),Summary(text),AreaRELATION → Areas DB (two-way "Projects"),GoalRELATION → Goals (two-way "Projects"). - ✅ Tasks —
Task(title),Done(checkbox),Do date(date),Priority(select: Top, Secondary),Type(select: Work, Personal),Tag(select: Triage, From Daily, Reminder, Shopping),Assignee(text),Executor(select: Me, Auto (Steward)),Deferred(number, default 0 — how many times the user pushed this task to a later day; bumped by the defer buttons below),ProjectRELATION → Projects (two-way "Tasks"). Add two table views: Work (filter Type=Work), Personal (filter Type=Personal). Defer buttons (manual — API cannot create Button properties). After the base exists, the user adds two Button properties in the Notion UI so a task can be pushed off today in one tap. The bootstrap routine cannot create these (the API has no button type), so it must instruct the user to add them (see "After — defer buttons" below) and confirm they exist:- → Tomorrow — edits this page: set
Do date= formuladateAdd(now(), 1, "days"), andDeferred=Deferred + 1. - → Next Week — edits this page: set
Do date= formuladateAdd(now(), 7, "days"), andDeferred=Deferred + 1.
- → Tomorrow — edits this page: set
- 💡 Ideas —
Idea(title),Type(select: Content, Startup, Other),Status(select: New, In progress, Drafted, Posted),Notes(text),AreaRELATION → Areas DB (two-way "Ideas"; optional). (Typeis the idea subtype;Drafted/Postedare mainly for Type=Content.) - 📚 Knowledge —
Title(title),Notes(text),AreaRELATION → Areas DB (two-way "Knowledge"; optional). Home forreferencenotes/facts. - 🗒️ Reviews —
Note(title),Type(select: Health, Sport, Career, Work, Money, Family, Other),Date(date). (Long format: one row = one review note; add many notes per area as separate rows over time.) - ⚠️ Not Recognized —
Note(title),Reason(text),Status(select: Open, Resolved),Source(select: Inbox voice, Daily notes). - 📡 Outbox —
Item(title),Type(select: notify, calendar, doc, sheet, other),Handler(select: Steward (MCP), Concierge Gateway),Payload(text),Status(select: Queued, Done, Failed),Source(text). - 📅 Today (a PAGE, not a database) — the daily driver. Create it as a page under Steward with:
- a heading
## 📝 Daily notesfollowed by an EMPTY capture area (no list items) — free text typed here is swept into Inbox by the daily routine (roll-day); - a divider;
- an inline linked view of Tasks (the day board). Configure it with the view DSL:
GROUP BY "Type"; FILTER "Done" = "false"; SORT BY "Do date" ASC, "Priority" ASC; SHOW "Task", "Do date", "Priority", "Tag", "Type"⚠️ Do NOT add theDo date <= todayfilter via DSL — the Notion MCP connector treats"today"as a literal string and produces an "Invalid DateTime" broken filter. After creating the view, instruct the user to add the date filter manually in the Notion UI: Filter → Do date → Start date → Is on or before → Today (the relative option, not Custom date). Work / Personal come from the grouping;Triageand overdue/carried items are surfaced by theTagcolour and the date sort (overdue rises to the top). Leave the page otherwise EMPTY of personal data —roll-dayfills and handles it daily.
- a heading
After — write the registry (REQUIRED, do not skip)
- Using your file tools, write
bases.local.jsonin the project root — a JSON map of base name → data-source ID for EVERY base created. Use the exact name keys frombases.local.example.json(Inbox, Tasks, Projects, Goals, Ideas, Knowledge, Areas DB, Reviews, Not Recognized, Outbox). Example:{"Inbox":"<data-source-id>", "Tasks":"<data-source-id>", ...}. - Also record the Today page under key
"Today"— this value is a page ID, not a data-source ID, soroll-daycan locate the daily page without searching. - This file is the single source of IDs for
roll-dayandsort-inbox— they read it instead of querying Notion. It is git-ignored (holds the user's own IDs). Without it the routine cannot file anything, so writing it is mandatory. - Report each base with its ID. Remind the user to connect their capture integration to Inbox (••• → Connections) so the iOS shortcut can POST to it.
- Leave all bases empty except the Area rows. Never insert personal data.
After — write the schema cache (REQUIRED, do not skip)
You just created every base, so you already know its exact title field, date fields, select options,
and the URL of each Area row. Persist that as the write-contract so sort-inbox never has to
re-discover it through failed writes. Write schema.cache.json in the project root (git-ignored,
same place as bases.local.json); shape mirrors schema.cache.example.json.
Per destination base that sort-inbox writes (Tasks, Goals, Ideas, Knowledge, Reviews,
Not Recognized, Outbox) record:
title— the exact title-property name to write the row name into (Tasks→Task, Goals→Goal, Ideas→Idea, Knowledge→Title, Reviews→Note, Not Recognized→Note, Outbox→Item).dateFields— every date property, by exact name (Tasks→["Do date"], Goals→["Target date"], Reviews→["Date"], others[]). These are written with the expanded formdate:<Field>:start, never bare.selects— every select property → its full allowed-option list, copied verbatim from the create step (e.g. GoalsHorizon: ["Yearly","Short-term"],Status: ["Not started","In progress","Done"]; IdeasType: ["Content","Startup","Other"],Status: ["New","In progress","Drafted","Posted"]; ReviewsType: ["Health","Sport","Career","Work","Money","Family","Other"]; TasksType/Priority/Tag/Executor; OutboxType/Handler/Status; Not RecognizedStatus/Source). Writing any value outside this list errors ("Invalid select value").
Then record the top-level maps:
areas— Area name (without the emoji prefix) → the full Notion URL of that Area row you just created (Career, Health, Sport, Money, Family, Content, Other). Relations require the full URL, not a bare id. Areas DB is canonical and effectively never changes, so this map is cached indefinitely.inbox.lastArchiveFailed— leavefalseat bootstrap;sort-inboxflips it only if an archive move fails. (Reviews needs no cached row — it is a plain create-row, one row per review note.)
This file is what makes the sort phase cheap: with it present, sort-inbox reads field names,
formats, select values, and Area URLs from disk instead of fetching base schemas or learning them
through API errors. Writing it here is mandatory.
After — defer buttons (REQUIRED, manual UI step)
The Notion API has no Button property type, so neither this routine nor roll-day can create the
defer buttons programmatically — they must be added by hand once, in the Notion UI. Walk the user
through it and confirm both exist before finishing:
- Open the ✅ Tasks database → + (add property) → type Button → name it → Tomorrow.
- Action Edit pages → this page → add two edits:
Do date→ Set to → switch to a formula and enterdateAdd(now(), 1, "days").Deferred→ Set to → formulaDeferred + 1.
- Repeat for a second button named → Next Week, identical but
dateAdd(now(), 7, "days"). - (Optional) On the Today linked Tasks view, show the two button columns and the
Deferredcolumn so a task can be pushed straight from the morning board in one tap.
Once present, a task the user does not want today leaves the Today board the moment they tap a button
(its Do date moves into the future, so the Do date <= today filter drops it), and Deferred
records how often it has been pushed — roll-day surfaces chronically-deferred tasks from that count.
Rules
- Relations are two-way (DUAL); the back-relation appears automatically on the target base.
- Use exact names/casing from
conventions.md. Do not invent extra fields. - If a base already exists, update it to match rather than creating a duplicate.