Mk Notes
Available actions

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

InputDescriptionRequiredDefault
inputThe path to the markdown file or directory to synchronizetrue-
destinationThe Notion page or database URL where you want to synchronize your markdown filestrue-
notion-api-keyYour Notion secret tokentrue-
cleanClean sync mode - removes ALL existing content from the destination before syncingfalsefalse
lockLock the Notion page after syncingfalsefalse
save-idSave Notion page IDs back to the source markdown files' frontmatter, enabling incremental updates on subsequent syncsfalsefalse
force-newForce creation of new pages, ignoring any existing page IDs in the markdown frontmatterfalsefalse
flatFlatten the result page tree, making all pages direct children of the destination instead of maintaining nested structuresfalsefalse

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 push

Force 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 push

Sync 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 clean option 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