Sync Action
Synchronize markdown files to Notion pages or databases using the sync GitHub Action
The sync action synchronizes your markdown files to a dedicated Notion page or database, maintaining the structure and formatting of your content.
Usage
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Sync markdown to Notion
uses: Myastr0/mk-notes/sync
with:
input: './docs' # The path to the markdown file or directory to synchronize
destination: 'https://notion.so/your-page-or-database-id'
notion-api-key: ${{ secrets.NOTION_API_KEY }}Secret management
Please note that you should not commit your Notion API key to your repository. You should use a GitHub Secret to store your Notion API key. You can find more information in the Setting Up Secrets guide.
Inputs
| Input | Description | Required | Default |
|---|---|---|---|
input | The path to the markdown file or directory to synchronize | true | - |
destination | The Notion page or database URL where you want to synchronize your markdown files | true | - |
notion-api-key | Your Notion secret token | true | - |
clean | Clean sync mode - removes ALL existing content from the destination before syncing | false | false |
lock | Lock the Notion page after syncing | false | false |
save-id | Save Notion page IDs back to the source markdown files' frontmatter, enabling incremental updates on subsequent syncs | false | false |
force-new | Force creation of new pages, ignoring any existing page IDs in the markdown frontmatter | false | false |
flat | Flatten the result page tree, making all pages direct children of the destination instead of maintaining nested structures | false | false |
Destination Types
Notion Page
When the destination is a Notion page, content is appended directly to the page. Child pages are created as sub-pages.
Notion Database
When the destination is a Notion database, pages are created as database items. This is useful for managing collections of documents where you want to leverage Notion's database features.
Outputs
This action does not produce any outputs.
Examples
Sync Documentation on Release
name: Sync Docs to Notion
on:
release:
types: [published]
jobs:
sync-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Sync documentation to Notion
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}Sync on Push to Main Branch
name: Auto-sync to Notion
on:
push:
branches: [main]
paths: ['docs/**']
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Sync to Notion
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}Clean Sync with Warning
name: Clean Sync Documentation
on:
workflow_dispatch:
jobs:
clean-sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Clean sync to Notion
uses: Myastr0/mk-notes/sync
with:
input: './content'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}
clean: 'true'Sync to a Notion Database
name: Sync to Notion Database
on:
push:
branches: [main]
paths: ['docs/**']
jobs:
sync-to-database:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Sync to Notion database
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DATABASE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}Sync to Database with Clean Mode
When using clean sync with a database, make sure your markdown files include an id in the frontmatter:
---
id: my-unique-doc-id
title: My Document
---
Content here...name: Clean Sync to Database
on:
workflow_dispatch:
jobs:
clean-sync-database:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Clean sync to Notion database
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DATABASE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}
clean: 'true'Sync with Save ID (Incremental Updates)
Use save-id to enable incremental updates. After syncing, the Notion page IDs are saved back to your markdown files, allowing subsequent syncs to update existing pages instead of creating duplicates.
Committing changes
When using save-id, you need to commit the updated markdown files back to your repository. The example below shows how to do this automatically.
name: Sync with Incremental Updates
on:
push:
branches: [main]
paths: ['docs/**']
jobs:
sync-incremental:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Sync to Notion with save-id
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}
save-id: 'true'
- name: Commit updated page IDs
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add docs/
git diff --staged --quiet || git commit -m "chore: update Notion page IDs"
git pushForce New Pages
Use force-new when you want to create new pages, ignoring any existing page IDs stored in the markdown frontmatter:
name: Force New Sync
on:
workflow_dispatch:
jobs:
force-new-sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Force create new pages in Notion
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}
force-new: 'true'Complete Reset with New IDs
Combine clean, force-new, and save-id to completely reset your synchronization:
name: Reset Sync
on:
workflow_dispatch:
jobs:
reset-sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Reset sync to Notion
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}
clean: 'true'
force-new: 'true'
save-id: 'true'
- name: Commit new page IDs
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add docs/
git diff --staged --quiet || git commit -m "chore: reset Notion page IDs"
git pushSync with Flat Structure
Use flat to create a flat list of pages instead of maintaining nested folder structures:
name: Flat Sync
on:
push:
branches: [main]
paths: ['docs/**']
jobs:
flat-sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Sync with flat structure
uses: Myastr0/mk-notes/sync
with:
input: './docs'
destination: ${{ secrets.NOTION_DOCS_PAGE_URL }}
notion-api-key: ${{ secrets.NOTION_API_KEY }}
flat: 'true'When flat: 'true' is used:
- All pages are created as direct children of the destination page
- The root node is skipped (if your directory has an
index.md, it becomes a child page) - Folder hierarchy is flattened into a simple list
- Useful for creating simple document lists or syncing to databases where you want all items at the same level
Important Notes
- For clean sync: The
cleanoption removes ALL existing content from the destination before syncing - For save-id: Remember to commit the updated markdown files back to your repository
- For force-new: Use with caution as it may create duplicate pages if used without
clean - For flat: When using
flat, the root node is skipped and all files become direct children. This is ideal for simple document lists or database syncs where hierarchy isn't needed - Use clean sync only when you're sure you want to replace content
- Always test with the preview action first
- Make sure your Notion integration has access to the target page or database