Skip to content

Repository files navigation

framer-cms-markdown

Publish Markdown content to Framer CMS.

This tool allows Git to become the source of truth for Framer CMS content. Content can be stored as Markdown, reviewed through pull requests, generated or updated by AI workflows, and published automatically to Framer.

Markdown → Git → Review → Framer CMS

Motivation

Framer is excellent for designing and publishing websites. However, as content becomes increasingly AI-generated and AI-maintained, the CMS UI can become a bottleneck.

Markdown is a better authoring format

Markdown is the native format for many AI workflows.

Compared to HTML or CMS-specific formats, Markdown is:

  • Easier for LLMs to generate and modify
  • More token-efficient
  • Human-readable
  • Easy to review and edit manually
  • Supported by virtually every AI and developer tool

As a result, content generation pipelines, AI agents, and human authors can all work against the same format.

Git is a better content store

When content is generated and updated by AI, reviewing changes becomes more important than editing content directly.

Git provides capabilities that traditional CMS interfaces struggle to match:

  • Meaningful diffs and change reviews
  • Pull-request based approval workflows
  • Full audit trail and history
  • Easy rollback of problematic AI-generated changes
  • Native integration with tools such as Claude Code, Cursor, and GitHub Actions
  • Direct filesystem access for scripts and automation

This makes Git a great source of truth for AI-managed content.

Framer remains the presentation layer

Content is authored and maintained as Markdown files in Git, while Framer remains responsible for design, layout, and publishing.

The primary purpose of this project is to sync Markdown content into Framer CMS automatically. Exporting Framer content to Markdown exists mainly to bootstrap an existing Framer collection into a Git-based workflow.

Installation

npm install
npm run build

Or run directly via npx:

npx framer-to-markdown --token <FRAMER_TOKEN_> --config config/blog.yml
npx markdown-to-framer --token <FRAMER_TOKEN> --config config/blog.yml

You can also provide the token via an environment variable:

export FRAMER_TOKEN=<token>

Configuration

Each sync target is defined in a YAML file.

Example:

site: https://framer.com/projects/MySite-37823594648842342348-12345
collection: Blog
content: content/blog
markdown: sections
metadata:
  - Title
  - Team
Option Required Description
site Yes Framer project URL or project ID.
collection Yes Framer CMS collection name or ID.
content No Directory containing Markdown files. Defaults to content/<collection>.
markdown Yes Defines where page content is stored. Either a Framer field name (e.g. Content) or the special value sections.
metadata No List of Framer fields that should be mapped to YAML frontmatter. These fields are copied verbatim between Framer and frontmatter.

When markdown: sections is used:

  • Section NN HTML fields are combined into a single Markdown document during export
  • Markdown headings are split back into sections during import
  • Section NN Title fields are populated from the first heading of each section

This is useful for content where sections should remain individually addressable in Framer. Each section can be rendered with its own anchor links and table of contents entries, improving navigation for both users, search engines (SEO), and AI chatbots that consume web content. Structured pages with stable section anchors are generally easier to reference, cite, and retrieve than a single large content block.

Identity and Slugs

CMS items are matched by their slug.

  • Existing items are updated when the slug already exists
  • New items are created when the slug does not exist
  • If no slug is present, one is generated from the filename

Markdown Format

Example:

---
slug: customer-feedback-analysis
Title: Customer Feedback Analysis
Team: Product
---

# Overview

Content goes here.

## FAQ

### Why do I see this error?

This is due to...

Exporting Framer → Markdown

Typically used once to bootstrap an existing Framer collection into Git:

npx framer-to-markdown \
  --token="$FRAMER_TOKEN" \
  --config=config/blog.yml

The exporter:

  • Reads all items from the collection
  • Converts Framer HTML content to Markdown
  • Copies configured metadata fields into frontmatter
  • Removes Framer HTML comments
  • Formats output using Prettier
  • Writes one Markdown file per CMS item

Importing Markdown → Framer

npx markdown-to-framer \
  --token="$FRAMER_TOKEN" \
  --config=config/blog.yml

The importer:

  • Reads all Markdown files
  • Parses YAML frontmatter
  • Maps metadata fields back to Framer
  • Converts Markdown to Framer content
  • Creates or updates items by slug

For FAQ-style content, JSON-LD FAQ schema is generated automatically and written to a JSON-LD field when present.

Import is additive:

  • Existing items are updated by slug
  • Missing items are created
  • Items that exist in Framer but not in Markdown are left unchanged

GitHub Workflow

One way to use this tool is to make Git the source of truth for all CMS content.

Content is stored as Markdown files in a Git repository. Humans, AI agents, and automation workflows interact exclusively with those files. Whenever content changes, a GitHub Action publishes the updates to Framer CMS.

In this setup, Framer becomes primarily a presentation layer. Content is authored, reviewed, versioned, and generated in Git, while Framer remains responsible for design, layout, and publishing.

This effectively creates a headless content workflow on top of Framer CMS.

Example Github Action:

name: Publish to Framer

on:
  push:
    branches:
      - main

jobs:
  markdown-to-framer:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npx markdown-to-framer --token="${{ secrets.FRAMER_TOKEN }}" --config=blog/framer-sync.yml

Flow:

Markdown
    ↓
Pull Request
    ↓
Merge
    ↓
GitHub Action
    ↓
Framer CMS

About

Sync's Framer CMS content from/to markdown

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages