The short version
This workflow uses Notion for writing, Astro for static site generation, and Cloudflare Pages for deployment. When an article is ready, press the “Publish” button in Notion to sync it to the website.
When this setup is useful
-
You already have an Astro site and want to keep its current design.
-
You prefer writing in Notion instead of editing source files for every post.
-
You want article pages, an article index, and a sitemap generated automatically.
-
You still want GitHub Markdown as a fallback or long-term archive.
How it works
Notion article → “Publish” button → Cloudflare Deploy Hook → Cloudflare Pages build → Astro reads Notion → article page / article index / articles.json / sitemap.xmlNotion is read during the Cloudflare build, not live in a visitor’s browser. The resulting site stays static and fast, and the Notion token is never exposed to readers.
Required Notion database properties
Use a full-page database with these properties:
| Property | Type | Purpose |
|---|---|---|
title | Title | Article title |
Slug | Rich text | URL suffix, such as my-first-post |
Status | Status | Only pages with Published are deployed |
Language | Select | zh-CN or en; defaults to Chinese when omitted |
Translation Key | Rich text | Shared key linking a reviewed Chinese and English version |
These optional properties are recommended:
| Property | Type | Purpose |
|---|---|---|
Date | Date | Publication date; page creation time is used when absent |
Description | Rich text | Article summary; the first paragraph is used when absent |
Write the article body directly in the Notion page. The site creates the H1 from title, so start the body with an H2 when appropriate. Publish each language as its own Notion page. When a translation is ready, give both pages the same Translation Key; the site will connect them with a language switch and hreflang metadata.
Essential Cloudflare Pages settings
Open Settings → Variables and secrets in the Cloudflare Pages project and add these values to the Production environment:
| Variable | Type | Value |
|---|---|---|
NOTION_TOKEN | Secret | A Notion Internal Integration Token |
NOTION_DATA_SOURCE_ID | Plaintext | The Notion data source UUID |
NOTION_PUBLISHED_STATUS | Optional plaintext | Published; this is the default when omitted |
Use NOTION_DATA_SOURCE_ID, not NOTION_DATABASE_ID. Treat both the Notion token and the Deploy Hook URL as secrets: never commit them to GitHub or include them in public posts or screenshots.
The expected build settings are:
| Setting | Value |
|---|---|
| Production branch | main |
| Build command | npm run build |
| Build output directory | dist |
One-time setup: Deploy Hook and Notion button
-
In Cloudflare Pages, open Settings → Build → Deploy hooks and create a hook.
-
Name it something clear, such as
notion-publish-youuc, and select themainbranch. -
Copy the generated Webhook URL and keep it private.
-
In the Notion database, create a Button property named “Publish”.
-
Add these actions to the button, in order:
-
Edit property: set the current page’s
StatustoPublished. -
Send webhook: paste the Cloudflare Deploy Hook URL.
-
-
Save the button.
One press now changes the publication state and starts a production build.
Everyday publishing workflow
-
Create a Notion page and fill in
title,Slug, and, when useful,DateandDescription. -
Write and review the page content, formatting, and links.
-
Press “Publish” in that article row.
-
Wait about 30–60 seconds, then visit
/articles/your-slug/. -
Confirm that the post also appears in the article index,
/articles.json, and/sitemap.xml.
Updating or unpublishing an article
-
Update a published article: edit it in Notion, then press “Publish” again to trigger a new build.
-
Unpublish an article: change
Statusto anything other thanPublished, then trigger a deployment. The next build removes it from the site. -
When the webhook is unavailable: manually start a Production deployment in Cloudflare Pages; it will still sync Notion content.
Using Notion and GitHub Markdown together
The site accepts two article sources:
-
GitHub Markdown: add files to
content/articles/and commit tomain. -
Notion: pages with
Status = Publishedare synced during the build.
Both sources are merged into the same article index, homepage archive, articles.json, and sitemap.xml. Keep every Slug unique to avoid collisions.
Troubleshooting checklist
| Symptom | Check first |
|---|---|
| The build succeeds but no article appears | Confirm that Production has both NOTION_TOKEN and NOTION_DATA_SOURCE_ID |
| The build says Notion is not configured | Check variable names, scope, and that changes were saved |
| A Notion page is not synced | Confirm Status is Published and the integration has access to the data source |
| The article URL does not open | Ensure the Slug is unique and uses only letters, numbers, and hyphens |
| Site content did not change after an edit | Press “Publish” again or trigger a manual deployment |
AI summary and retrieval keywords
AI summary: This guide explains how to use Notion as the writing interface for an Astro static blog, trigger a Cloudflare Pages build with a Deploy Hook, and automatically produce article pages, an article index, a JSON index, and an XML sitemap from published Notion pages.
Keywords: Notion CMS, Notion blog, Astro Notion integration, Cloudflare Pages, Deploy Hook, static site publishing, Notion webhook, Markdown and Notion workflow, article sync, XML sitemap, SEO.
FAQ
Why do Notion edits require a new deployment?
The content is written into the static site at build time. This keeps the site fast and prevents the token from reaching visitors’ browsers.
Can I use GitHub Markdown only?
Yes. Notion is an additional visual writing interface; it does not replace the existing Markdown workflow.
Can the Deploy Hook URL be public?
No. Anyone with the URL can trigger a build, so store it like a password.