Decap CMS Integration with Static Site Generators
Decap CMS doesn't depend on specific SSG — works with filesystem and Git. But each generator has conventions for content structure, frontmatter, file paths. Proper integration means CMS writes files in format SSG understands without extra processing.
Next.js + Decap CMS
Next.js reads content via fs, gray-matter, or @next/mdx. Example scheme:
# public/admin/config.yml
backend:
name: github
repo: myorg/my-next-site
branch: main
media_folder: public/images
public_folder: /images
collections:
- name: posts
label: Articles
folder: _content/posts
create: true
slug: "{{slug}}"
extension: mdx
format: frontmatter
fields:
- { label: Title, name: title, widget: string }
- { label: Date, name: date, widget: datetime }
- { label: Body, name: body, widget: markdown }
Read in Next.js:
// lib/posts.ts
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
const postsDir = path.join(process.cwd(), '_content/posts')
export function getAllPosts() {
const files = fs.readdirSync(postsDir)
return files
.filter(f => f.endsWith('.mdx'))
.map(file => {
const raw = fs.readFileSync(path.join(postsDir, file), 'utf8')
const { data, content } = matter(raw)
return { slug: file.replace('.mdx', ''), ...data, content }
})
}
Astro + Decap CMS
Astro has built-in Content Collections system validating frontmatter via Zod. Config must match:
# Decap collection
collections:
- name: blog
folder: src/content/blog
fields:
- { name: title, widget: string }
- { name: pubDate, widget: datetime }
- { name: body, widget: markdown }
// src/content/config.ts
import { defineCollection, z } from 'astro:content'
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pubDate: z.coerce.date(),
}),
})
export const collections = { blog }
Hugo + Decap CMS
Hugo uses content/ directory. Frontmatter can be YAML, TOML, or JSON. Decap writes YAML by default:
# static/admin/config.yml
collections:
- name: posts
label: Posts
folder: content/posts
create: true
slug: "{{slug}}"
fields:
- { name: title, widget: string }
- { name: date, widget: datetime }
- { name: body, widget: markdown }
Hugo template reads without adapters — frontmatter available as .Params:
{{/* layouts/posts/single.html */}}
<article>
<h1>{{ .Title }}</h1>
<time>{{ .Date.Format "02.01.2006" }}</time>
{{ .Content }}
</article>
Netlify/Vercel Auto-Deploy Webhook
When editor publishes, Decap commits to Git. Need to trigger build:
Netlify — Build Hooks:
Settings → Build & deploy → Build hooks → Add build hook
Copy URL and add to GitHub repo Settings → Webhooks.
Vercel — Deploy Hooks:
Project Settings → Git → Deploy Hooks
URL like https://api.vercel.com/v1/integrations/deploy/prj_xxx/yyy.
Preview of Drafts
With editorial_workflow: true, drafts live in separate branches. For preview, setup Deploy Previews:
- Netlify auto-deploys each branch on unique URL
- Vercel does same via Preview Deployments
Editor sees "Preview" button — opens draft's preview deploy.
Timeline
Integration with existing SSG: 1 day. With i18n, editorial workflow: 2–3 days.







