<aside> 🚧
This product is under development so we recommend you try it out in a new workspace vs. your primary workspace to avoid any issues.
⚠️ There may be breaking changes until we’re fully launched. ⚠️
You will not be able to actually try this product until your accepted. To start the process, fill out the sign up form. While you wait you should be able to start building the scripts 🙌
Please provide any feedback or bugs through Feedback Tracker
</aside>
Notion as Code allows you to build and update Notion programmatically in bulk. Instead of having to make individual public API requests, you can describe the final state and we handle updating your workspace to match.
CleanShot 2026-07-09 at 15.50.19.mp4
Notion as code is:
A Notion as code script might look something like this ↓
function createProjectHubSimple() {
// Define a teamspace
const teamspace = space.teamspace({
resourceId: "main-ts",
parent: { type: "resourceId", resourceId: "my-space" }
name: "Main",
accessLevel: "default",
})
// Add a top-level page in the teamspace with some markdown content
const hub = teamspace.addPage({
resourceId: "hub-page",
icon: { type: "emoji", emoji: "🗂️" },
properties: { title: notion.text("Project Hub") },
content: [
"# Team",
"",
'<page url="{{getting-started}}">Getting Started</page>',
"",
"# Policies",
].join("\n"),
})
// Add a page nested in the top-level page
notion.page({
resourceId: "getting-started",
parent: { type: "resourceId", resourceId: hub.resourceId },
icon: { type: "emoji", emoji: "📘" },
properties: { title: notion.text("Getting Started") },
content: [
"# Welcome",
"This is the Getting Started page for the project.",
"- Sign in",
"- Read the onboarding docs",
].join("\n"),
})
}
You’ll notice this script doesn’t have any IDs, but instead uses resource IDs as the unique identifier. After the first deploy of the script, you’ll get back the mappings from resource ID to actual notion records that were created ↓
{
"my-space": { "id": "123", "table": "space" },
"hub-page": { "id": "456", "table": "block" },
"getting-started": { "id": "789", "table": "block" }
// and so on...
}
With this mapping, you can make changes to your script and then re-deploy to make changes to the actual records in Notion. And repeat ↺

Since the script is not coupled to one workspace, you can easily have multiple mappings of resource IDs to actual notion records allowing you to use the same script to deploy many workspaces.
Since the script is code, you can also utilize variables and loops to re-use common patterns easily (e.g. build 10 teams that all have a very similar structure and just need some nouns renamed).
<aside> <img src="/icons/verified_purple.svg" alt="/icons/verified_purple.svg" width="40px" />
For the alpha, this will be the smoothest path as it handles a lot of the complexity for you.
</aside>