Publishing
GitHub (Static Sites)
AvailablePublish to any static site — Next.js, Astro, Hugo, Jekyll, Gatsby, Eleventy — by committing markdown files with YAML frontmatter to a GitHub repo. Your existing CI pipeline rebuilds the site. No middleware, no runtime, no vendor lock-in.
Prerequisites
- A GitHub repository with your static site source.
- A CI/CD setup that rebuilds on push (Vercel, Netlify, Cloudflare Pages, GitHub Pages — all auto-rebuild by default).
- A Fine-Grained Personal Access Token with Contents: Read and write permission for this single repo.
Setup guide
- Go to GitHub → Settings → Developer settings → Fine-grained tokens.
- Click Generate new token. Name it
KwikScaleAI. - Set Repository access to Only select repositories, pick the repo you want to publish to.
- Under Repository permissions, set Contents to Read and write. Leave all other permissions at “No access.”
- Generate the token, copy it. You cannot see it again.
- In KwikScaleAI: Integrations → GitHub → Connect. Fill in owner, repo, branch, content path, and paste the PAT.
- Click Test connection. KwikScaleAI checks that the repo exists, the token has the right permission, and the branch is valid.
How it works
For each approved article, KwikScaleAI makes two or three HTTP calls to GitHub's Contents API:
GET /repos/{owner}/{repo}/contents/{path}— look up the current SHA (only on updates). A 404 means the file doesn't exist yet → treat as create.PUT /repos/{owner}/{repo}/contents/{path}— create or update the file. Base64-encoded content, configurable commit author and message.
Auth is Authorization: Bearer {personalAccessToken}. The commit triggers your CI, your site rebuilds, the article goes live. KwikScaleAI stores the file path as the cmsPostId so updates hit the same file on re-publish.
Frontmatter format
Every article is committed as a markdown file with a YAML frontmatter block at the top. The standard fields below cover most SSG themes — see supported SSG notes below for any theme-specific quirks.
---
title: "How We Doubled Organic Traffic in 90 Days"
slug: "how-we-doubled-organic-traffic"
date: "2026-04-16T12:00:00.000Z"
description: "The exact playbook we used to 2x traffic..."
tags: ["seo", "case-study", "growth"]
draft: false
---
# How We Doubled Organic Traffic in 90 Days
Lorem ipsum dolor sit amet, consectetur adipiscing elit...Configuration
| Parameter | Type | Required | Description |
|---|---|---|---|
| owner | string | Required | GitHub username or organization that owns the repo. |
| repo | string | Required | Repository name (without the owner prefix). |
| branch | string | Optional | Branch to commit to. Must already exist — the adapter does not create branches.Default: main |
| contentPath | string | Required | Directory inside the repo where markdown files go, e.g. content/blog, src/content/posts, _posts (Jekyll). Leading/trailing slashes are stripped. |
| personalAccessToken | string | Required | Fine-Grained PAT with Contents: Read and write on this repo. |
| fileExtension | 'md' | 'mdx' | Optional | md for standard markdown, mdx for Astro, Next.js MDX, Docusaurus, etc.Default: md |
| commitAuthorName | string | Optional | Name shown on the commit in git log.Default: KwikScaleAI |
| commitAuthorEmail | string (email) | Optional | Email shown on the commit.Default: bot@kwikscaleai.com |
| liveUrlPattern | string (URL) | Optional | Pattern for the public URL the article will have after rebuild, with {slug} as the placeholder. Example: https://example.com/blog/{slug}. When set, the dashboard shows a “View live” link. When unset, we fall back to the GitHub blob URL. |
ownerRequiredstring
GitHub username or organization that owns the repo.
repoRequiredstring
Repository name (without the owner prefix).
branchOptionalstring
Branch to commit to. Must already exist — the adapter does not create branches.
Default: main
contentPathRequiredstring
Directory inside the repo where markdown files go, e.g. content/blog, src/content/posts, _posts (Jekyll). Leading/trailing slashes are stripped.
personalAccessTokenRequiredstring
Fine-Grained PAT with Contents: Read and write on this repo.
fileExtensionOptional'md' | 'mdx'
md for standard markdown, mdx for Astro, Next.js MDX, Docusaurus, etc.
Default: md
commitAuthorNameOptionalstring
Name shown on the commit in git log.
Default: KwikScaleAI
commitAuthorEmailOptionalstring (email)
Email shown on the commit.
Default: bot@kwikscaleai.com
liveUrlPatternOptionalstring (URL)
Pattern for the public URL the article will have after rebuild, with {slug} as the placeholder. Example: https://example.com/blog/{slug}. When set, the dashboard shows a “View live” link. When unset, we fall back to the GitHub blob URL.
Supported static site generators
| SSG | Typical contentPath | Notes |
|---|---|---|
| Next.js (MDX) | src/content/blog or posts | Set fileExtension: mdx. Works with Contentlayer, MDX Remote, and native Next 15 MDX. |
| Astro | src/content/blog | Matches Astro's default content collections. Use fileExtension: md or mdx. |
| Hugo | content/posts | Hugo expects draft: false (which we emit) and date fields — both covered. |
| Jekyll | _posts | Jekyll requires the filename to start with a date, e.g. 2026-04-16-slug.md. Currently we name files {slug}.md — for Jekyll, a post-processing step in CI is needed. Not fully supported in v1. |
| Gatsby | content/blog | Uses the same frontmatter Gatsby's gatsby-transformer-remark reads. |
| Eleventy (11ty) | src/posts | Use the tags frontmatter; 11ty collections pick it up automatically. |
Configuring the live URL pattern
Set liveUrlPattern so the dashboard links to the public article URL — not the GitHub blob URL — after rebuild. Replace {slug} with wherever the slug appears in your URL structure:
- Blog under root:
https://example.com/{slug} - Blog under path:
https://example.com/blog/{slug} - Dated URLs:
https://example.com/blog/2026/{slug}— note the year must be static; dynamic date substitution isn't in v1.
Capabilities
Troubleshooting
Test connection returns 401 or 404
Test connection says 'PAT missing push permission'
Publishes succeed but the site doesn't rebuild
409 Conflict on update
The file ends up in the wrong folder
PAT works for reads but 403 on writes
FAQ
Which static site generators work with this integration?
Do I need to use a Fine-Grained PAT or a Classic PAT?
Can I commit to a non-default branch?
What happens when KwikScaleAI updates an existing article?
Is there a commit per article, or does KwikScaleAI batch?
Related
- Custom Webhook — if you want to build a PR-based workflow instead of direct commits.
- Integrations overview.
Ready to automate publishing?
Connect your site once. KwikScaleAI researches, writes, and publishes SEO content on autopilot.