From structured rows to polished articles — automatically

Open-source article publishing pipeline for Framer CMS, GitHub, and Markdown

Turn structured rows from CSV, NocoDB, Google Sheets, or JSON into validated articles — published to Framer CMS, GitHub, or Markdown without manual copy-paste.

Open source · Self-hosted · MIT licensed

PublishRail workflow: structured sources (CSV, JSON, NocoDB, Google Sheets) flow into a context step, then AI generation, then validation, then publishing to Markdown, GitHub, or Framer CMS.

Built for Framer CMS publishing

Publish straight to Framer CMS over Framer's server-side API — structured rows in, published collection items out.

  • Server-side

    Bearer-token calls to api.framer.com from your own environment.

  • Structured fields

    Title, slug, description, and body map to the Framer fields you configure.

  • Repeatable

    Every row runs the same generate → validate → publish path.

POST · api.framer.com
# each H2 → its own field
POST /…/collections/{id}/items

{
  "fieldData": {
    "title":      "Framer vs Webflow",
    "slug":       "framer-vs-webflow",
    "howItWorks": "## How it works …",
    "faq":        "## FAQ …"
  }
}

disabled by default · dry-run preview · creates published entries

New to the Framer API? Read the official Framer developers documentation for how server-side CMS access works. PublishRail is an independent open-source project and is not affiliated with or endorsed by Framer.

How PublishRail works

One configurable workflow — five stages, run identically for every row.

  1. Source

    Point the pipeline at a structured source. Each row becomes one article run.

    csvjsonnocodbsheets
  2. Context

    Positioning, messaging, and glossary files are injected into every prompt — not just the row.

    positioningmessagingglossary
  3. Generate

    A configurable AI provider writes the draft. Anthropic or any OpenAI-compatible endpoint.

    AnthropicOpenAIlocal
  4. Validate

    Deterministic checks then an optional AI judge. Below-threshold drafts are rewritten automatically.

    validatorsAI judgerewrite
  5. Publish

    Markdown, a GitHub folder, or a Framer CMS collection — single-body or section-mapped.

    MarkdownGitHubFramer

How Framer CMS section mapping works

Framer CMS section mapping lets PublishRail send individual sections of a generated article into predefined Framer CMS fields. Instead of placing an entire article in one rich-text field, the pipeline can map sections such as “How it works,” “Pricing comparison,” or “FAQ” into structured CMS fields automatically, based on the article's H2 (##) headings.

Article H2 section
maps to
Framer CMS field
How it works
howItWorks
Pricing comparison
pricingComparison
FAQ
faq

You define the heading-to-field mapping in your project config. The pipeline extracts each H2 section from the generated article and sends it to the corresponding Framer CMS field. Headings can be matched exactly or normalized, and unmapped sections can be ignored, warned on, appended to the body, or treated as an error.

One source-to-publish workflow

PublishRail reads from structured sources and publishes to file- and CMS-based destinations. Switch either end in your project config without rewriting the pipeline.

Publish from structured sources

Each row becomes one article run.

  • CSV
  • NocoDB
  • Google Sheets
  • JSON

Publish to your destination

Choose one or several targets per run.

  • Framer CMS
  • GitHub
  • Markdown

Validate before you publish

Deterministic checks, an optional AI judge, and dry-run previews — issues are caught in the pipeline, not your live CMS.

Deterministic checks

Fast, rule-based validators run without extra AI calls. They check article structure and formatting and flag issues by severity.

  • At least three H2 sections; no empty or duplicate headings
  • FAQ formatting and heading levels
  • Word-count range and overlong inline bold
  • Escaped-quote cleanup and banned “AI-tell” vocabulary
  • FAQ content aligned with its JSON-LD

AI judge & rewrite

When enabled, an AI judge scores the draft against your evaluation criteria and returns a decision.

  • Per-dimension scoring against your rubric
  • Automatic rewrite when a draft is below threshold
  • Re-evaluation after the rewrite
  • Configurable models and maximum rewrite count

Dry-run preview

The GitHub and Framer publishers default to dry run, so you preview before anything is sent.

  • See the exact payload that would be published
  • Framer dry run lists each mapped section and its size
  • Missing or unmapped headings are reported
  • Live publishing is an explicit, deliberate step

Validation helps teams catch issues early. It does not guarantee accuracy — review remains part of the workflow.

Who PublishRail is for

PublishRail is for teams that publish many structured articles and need a reliable workflow from source data to a live CMS entry. It is especially useful for Framer teams, content operations teams, agencies, product marketers, developer-led marketing teams, and technical teams that manage editorial production through spreadsheets, databases, GitHub, or AI models.

Framer teams

Publish structured entries straight into Framer CMS collections, including section-mapped fields.

Content ops & agencies

Run separate configurations per project or client, each with its own context, prompts, source, and target.

Developer-led marketing

Keep content in Git or a database and publish to Markdown or GitHub folders from the same run.

Self-hosted. MIT licensed. Bring your own keys.

PublishRail runs entirely on your own machine or server. Your content, context, API keys, and tokens stay in your environment — nothing is sent anywhere except the AI provider and publishing targets you configure.

The publisher architecture is extensible: implement the interface to add your own output target without modifying core pipeline code.

  • MIT licensed — use it, fork it, modify it
  • Self-hosted Node.js app with an optional local web UI
  • API keys and tokens stay in your own .env
  • Model flexibility — Anthropic or any OpenAI-compatible provider
  • Dry-run mode for the GitHub and Framer publishers

View the source on GitHub

.env
# AI provider — anthropic | openai (OpenAI-compatible)
AI_PROVIDER=anthropic
AI_MODEL=claude-opus-4-8
AI_API_KEY=your_api_key_here

# Source (set the type in your project config)
NOCODB_BASE_URL=https://nocodb.example.com
NOCODB_API_TOKEN=your_token_here

# GitHub publisher (optional, disabled by default)
GITHUB_TOKEN=your_github_token_here
GITHUB_OWNER=your-org
GITHUB_REPO=your-repo

# Framer publisher (optional, disabled by default)
FRAMER_TOKEN=your_framer_token_here
FRAMER_COLLECTION_ID=collection_id_here

Frequently asked questions

Can PublishRail publish directly to Framer CMS?

Yes. PublishRail publishes directly to a Framer CMS collection using Framer's server-side HTTP API. Add a Framer API token and collection ID, enable the Framer target in your project config, and each generated article becomes a new published item in your collection. Framer publishing is disabled by default, and you can run it in dry-run mode first to preview the exact payload before anything is sent.

Does PublishRail use the Framer Server API?

Yes. PublishRail calls Framer's server-side API at api.framer.com, authenticating with a bearer token you store in your own environment. Because the requests happen server-side, the pipeline can create CMS items programmatically without opening the Framer editor for each article. You supply the API token and collection ID, and PublishRail sends structured field data for every row it processes.

How does PublishRail map article sections to Framer CMS fields?

In section-mapped mode, PublishRail splits a generated article by its H2 (##) headings and sends each section to a specific Framer CMS field you define. You configure a mapping of heading text to field name in your project config — for example, “FAQ” to a faq field. Headings can be matched exactly or normalized, and unmapped sections can be ignored, warned on, appended to the body, or treated as an error.

Can PublishRail publish content from Google Sheets or NocoDB to Framer?

Yes. PublishRail reads structured rows from Google Sheets, NocoDB, CSV, or JSON, and any of those sources can feed the Framer CMS target. You set the source type in your project config; the rest of the pipeline — generation, validation, and publishing — stays the same. A row in a NocoDB table or a Google Sheet can become a published Framer CMS item in a single run.

Can PublishRail publish articles to GitHub as Markdown?

Yes. The GitHub target commits each article as a Markdown file into a folder of a repository you choose, using the GitHub Contents API — no local git checkout required. You configure the owner, repository, branch, and folder, and the commit message is templated per article. Like the other publishers, it supports dry-run mode so you can preview commits before they are created.

Is PublishRail self-hosted?

Yes. PublishRail is self-hosted and runs entirely on your own machine or server. It is a Node.js application you clone and run yourself, with an optional local web UI for managing runs and editing prompts. Your API keys and tokens live in your local environment, and nothing is sent anywhere except the AI provider and publishing targets you explicitly configure.

Does PublishRail support dry runs before publishing?

Yes, for the GitHub and Framer targets. Dry-run mode builds the full payload and prints exactly what would be published — for Framer, that includes each mapped section, its character count, and any missing or unmapped headings — without calling the remote API. Dry run is the default for these publishers, so live publishing is something you opt into deliberately rather than by accident.

What does PublishRail validate before publishing an article?

PublishRail runs deterministic local checks plus an optional AI judge. Local validators cover article structure (a minimum number of H2 sections, no empty or duplicate headings), FAQ formatting, word count, escaped-quote cleanup, banned “AI-tell” vocabulary, and alignment between FAQ content and its JSON-LD. The AI judge then scores the draft against your criteria and can trigger an automatic rewrite, helping teams catch issues before content reaches Framer CMS, GitHub, or Markdown.