Overview
Blog posts are stored in a Notion database (NOTION_BLOG_DB_ID) and synced as MDX files to src/content/blog/ during the pre-build process. Only posts marked as “public” are synced and published to your site.
Database Schema
Your Notion blog database must include these properties (defined insrc/content.config.ts:15-23):
| Property | Type | Description |
|---|---|---|
| title | Title | Post title (required) |
| description | Text | SEO meta description |
| path | Text | URL slug (e.g., /blog/my-post) |
| published | Date | Publication date |
| tags | Text | Comma-separated tags |
| public | Checkbox | Visibility toggle (only true posts sync) |
| dates | Text | Optional date range for the content |
| lastEditedTime | Last edited time | Auto-updated by Notion |
The
public checkbox must be enabled for a post to be synced and published. This allows you to draft posts in Notion without publishing them immediately.Creating a Blog Post
Add a new page to your Notion blog database
Create a new entry in your Notion database (the one specified by
NOTION_BLOG_DB_ID in your environment variables).Fill in the required properties
Set the following properties:
- title: Your post title
- description: A brief description for SEO
- path: URL slug (e.g.,
/blog/my-first-post) - published: Publication date
- tags: Categories or tags (comma-separated)
- public: Check this box when ready to publish
Write your content
Write your blog post content using Notion’s block editor. See Notion Blocks for supported block types.
Content Sync Process
The sync process happens automatically during the build (src/lib/notion-download.ts:30-92):
- Query: Fetches all pages from your blog database where
public: true - Filter: Only syncs posts that have been edited since last sync (using
lastEditedTime) - Parse: Converts Notion blocks to Markdown using
parseBlocks() - Assets: Downloads images and media to
src/assets/orpublic/assets/ - Generate: Creates MDX file at
src/content/blog/{page-id}.mdxwith YAML frontmatter
The sync is incremental - only posts that have been edited since the last build are re-downloaded. This speeds up build times significantly.
Generated MDX Structure
When a blog post is synced, it generates an MDX file like this:Accessing Blog Posts in Code
Use Astro’s content collections API to query blog posts:Updating a Blog Post
Unpublishing a Post
To remove a post from your site without deleting it from Notion:- Uncheck the public checkbox in Notion
- Delete the corresponding MDX file from
src/content/blog/ - Rebuild your site
Best Practices
Use descriptive path slugs
Use descriptive path slugs
Choose clear, SEO-friendly URL paths like
/blog/notion-cms-setup instead of /blog/post1.Write quality descriptions
Write quality descriptions
The
description field is used for SEO meta tags. Write compelling 150-160 character summaries.Tag consistently
Tag consistently
Use a consistent tagging system (e.g., “dev”, “design”, “writing”) to make filtering and categorization easier.
Preview before publishing
Preview before publishing
Keep the
public checkbox unchecked while drafting. Enable it only when you’re ready to publish.Troubleshooting
Post not showing up after sync
Check:publiccheckbox is enabled in NotionNOTION_BLOG_DB_IDenvironment variable is correct- Notion integration has access to the database
- MDX file exists in
src/content/blog/
Build fails with schema errors
Check:- All required properties (title, description, path, etc.) are filled in Notion
- Property types match the schema in
src/content.config.ts - No special characters in property values that might break YAML parsing
Images not loading
Check:- Images are properly embedded in Notion (not just linked)
- Image files exist in
src/assets/orpublic/assets/ - Image paths in MDX use correct syntax