{
  "id": 14994891,
  "title": "GitHub Contents API CMS in Next.js: Publish Markdown Without a Database",
  "url": "https://urgent.news/2026/10/16/github-contents-api-cms-in-next-js-publish-markdown-without-a-database",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-16T16:45:50.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/najmulcodes/github-contents-api-cms-in-nextjs-publish-markdown-without-a-database-4oge"
  },
  "original_language": "en",
  "account": "Publishing Markdown articles without a database is possible thanks to the GitHub Contents API in Next.js 16 (App Router). To create or update an article, a user submits a PUT request to the GitHub API, specifying the file path, the article content as a base64-encoded string, and the branch to commit to. If the branch is not specified, the article will be committed to the \"main\" branch.\n\nThe GitHub Contents API is set up as a CMS by creating Markdown files in the \"content/articles/\" directory, with the slug of the article used as the file name (e.g., \"slug.md\"). The server-side admin runs within the same Next.js app, keeping the GitHub token secure and out of the browser.\n\nTo authenticate with the GitHub API, a fine-grained personal access token is required, with read and write permissions limited to the specific repository. The token should be stored as an environment variable (GITHUB_TOKEN) rather than a publicly exposed variable. Once the token is set up, it can be used to read and write files in the repository.\n\nWhen reading an article, the server sends a GET request to the GitHub API with the article's slug and branch specified. If the article is found, the server extracts the Markdown content from the response and returns it. If the article is not found, the server returns null.\n\nTo write an article, the server sends a PUT request with the article's slug, Markdown content, and current SHA (if available). If the file does not exist or the SHA is stale, the server will return a 409 error. In this case, the server should inform the editor instead of retrying the request.",
  "summary": "You can publish from a browser without running a database: an admin form commits a Markdown file to your GitHub repo, and the host redeploys. This post shows that GitHub Contents API CMS pattern in Next.js 16 (App Router), the one rule that trips people up ( sha ), and how to handle a 409. Status first: I built this admin and ran 41 API checks against mock GitHub, dev.to and IndexNow servers. I…",
  "key_points": [
    "GitHub Contents API enables Markdown publishing without a database in Next.js 16 (App Router).",
    "The GitHub token is stored as an environment variable (GITHUBTOKEN) for secure authentication."
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}