JEKYLL CMS
VISUAL EDITOR
WITH md0
Jekyll was built for Git from day one. md0 adds the visual editor layer on top. Your _posts/ folder stays the source of truth. Nothing changes about how Jekyll builds.
Why This Pairing Works
Jekyll + md0
Jekyll pioneered the git-native CMS idea: content files live in the repo, a static build reads them, and GitHub Pages deploys the result. The problem has always been that editing raw markdown files with YAML front matter is not friendly for non-technical contributors.
md0 sits between the editor and the GitHub repo. Writers open a visual editor, fill in a form for the front matter, and write in a WYSIWYG interface. When they save, md0 commits a properly-formatted Jekyll post file to the repo. Jekyll and GitHub Pages never know md0 is involved.
No Ruby gems to install. No Gemfile changes. No admin directory added to your repo. The stack stays simple: GitHub repo, Jekyll build, GitHub Pages deploy.
ENTIRELY FREE STACK
GitHub Pages hosting, Jekyll builds, and md0 CMS editing are all free for public repos. No credit card, no post limits, no page limits.
AUTO DEPLOY ON SAVE
Save in md0 and a commit lands in your repo. GitHub Pages detects the push, triggers a Jekyll rebuild, and the post goes live within seconds.
ZERO JEKYLL CHANGES
No new gems, no config edits, no admin directory. md0 reads your existing folder structure and maps directly to it.
FRONTMATTER AS FORM
Jekyll front matter fields like layout, categories, and tags become typed form inputs. No more hand-editing YAML.
Before You Start
Prerequisites
A Jekyll site hosted on GitHub
Your Jekyll project needs to live in a GitHub repository. GitHub Pages repos work perfectly. Private repos work too on paid md0 plans.
Markdown content in _posts/ or other directories
md0 works with any directory that contains .md files. Standard Jekyll puts blog posts in _posts/, pages in _pages/, and custom collections in directories you define in _config.yml.
An md0 account
Free for public repositories. Sign up at cms.md0.io using GitHub OAuth. The whole sign-up takes under a minute.
Jekyll Content Model
How Jekyll Content Is Organized
Jekyll has a specific folder convention. Understanding it helps you configure md0 correctly.
_posts/ - Blog Posts
Blog posts live in _posts/ and follow a strict naming format: YYYY-MM-DD-slug.md. The date prefix is not optional in Jekyll. Jekyll reads the date from the filename and uses it to determine the post URL and to sort posts in collections.
Example filenames
_posts/2026-01-15-getting-started-with-jekyll.md _posts/2026-02-03-building-a-portfolio-site.md _posts/2026-06-29-my-latest-post.md
md0 handles this naming format automatically. When you create a new post in md0, it generates the date-prefixed filename based on today's date and the title you enter. You can override the filename before saving.
_pages/ and Root-Level Pages
Static pages like about.md, contact.md, or projects.md often live at the repo root or in a _pages/ directory. These do not require date-prefixed filenames. They are regular markdown files with a layout field in the front matter.
Custom Collections
Jekyll supports custom content types called collections. You define them in _config.yml and their files live in underscore-prefixed directories like _projects/, _docs/, or _team/.
_config.yml - defining collections
collections:
projects:
output: true
permalink: /projects/:name/
docs:
output: true
permalink: /docs/:name/
defaults:
- scope:
path: ""
type: "projects"
values:
layout: "project"md0 maps to these directories using the same path you define in _config.yml. Point md0 at _projects/ and it reads and writes files there exactly as Jekyll expects.
Standard Jekyll Front Matter
A typical Jekyll post uses front matter like this:
_posts/2026-01-15-my-post.md
--- layout: post title: "Getting Started with Jekyll" date: 2026-01-15 09:00:00 +0000 categories: [tutorial, jekyll] tags: [static-site, github-pages] author: Jane Smith permalink: /tutorial/getting-started/ published: true --- Your post content goes here. Write in standard Markdown.
md0 reads your existing files and uses the field names it finds to suggest a schema. You confirm and extend this schema in md0's schema builder.
Step 1
Connect Your Jekyll Repository
Sign in with GitHub OAuth
Go to cms.md0.io and click Sign in with GitHub. GitHub asks you to authorize md0 and select which repositories to grant access to. You can limit access to your Jekyll repo specifically rather than granting blanket access to all repos.
md0 requests read and write access to repository contents. This is what allows it to read your existing posts and commit new ones when you save.
Select Your Jekyll Repository
After authentication, you land on the repository selection screen. Pick your Jekyll project. If it does not appear, check your GitHub OAuth app settings and grant md0 access to that specific repo.
Select the branch you deploy from. For GitHub Pages, this is typically main, master, or a dedicated gh-pages branch depending on how your repo is configured.
What md0 Detects Automatically
Once connected, md0 scans the repo and identifies:
- -Directories that contain
.mdfiles, flagging common Jekyll paths like_posts/and_pages/ - -Front matter field names already present in your existing files
- -Whether your post filenames follow the Jekyll date-prefix convention
- -Custom collections defined in
_config.yml
Step 2
Define Your Content Collections
A collection in md0 maps to a directory in your Jekyll repo. You tell md0 the path, the file extension, and which front matter fields to display in the editor. md0 stores this config in your repo as a committed file.
Example: _posts collection schema
{
"name": "posts",
"path": "_posts",
"extension": "md",
"filenameFormat": "YYYY-MM-DD-{slug}",
"fields": [
{ "name": "layout", "type": "select", "options": ["post", "page"], "default": "post" },
{ "name": "title", "type": "text", "required": true },
{ "name": "date", "type": "date", "required": true },
{ "name": "categories", "type": "text" },
{ "name": "tags", "type": "text" },
{ "name": "author", "type": "text" },
{ "name": "published", "type": "boolean", "default": true }
]
}path
Set this to _posts for your blog posts. For custom collections, use the directory name from your _config.yml (for example _projects or _docs). The leading underscore is part of the path.
filenameFormat
Jekyll requires the YYYY-MM-DD-slug format for _posts/ files. md0 auto-populates the date from today and generates the slug from the title. Custom collections do not require date-prefixed filenames. Leave this field out for those.
layout field
The layout field tells Jekyll which template to use. Make it a select type with options matching the layout filenames in your _layouts/ directory (without the .html extension). This prevents typos and keeps your content consistent.
published field
Set this as a boolean field with a default of true. Jekyll reads published: false and excludes the post from the build output. This gives editors a draft toggle without creating separate branch workflows.
Adding Multiple Collections
You can create separate collections in md0 for each Jekyll content type. A typical setup:
_postsBlog posts (date-prefixed filenames)_pagesStatic pages (no date prefix)_projectsPortfolio items_docsDocumentation pagesStep 3
Jekyll-Specific Front Matter Fields
Jekyll reads specific front matter keys and uses them to control routing, templating, and build behavior. md0 maps each of these to the appropriate form input type.
layout
Tells Jekyll which HTML template to wrap the content in. Maps to a filename inside _layouts/. Use a select field type in md0 with options like post, page, default.
{ "name": "layout", "type": "select", "options": ["post", "page", "default"] }permalink
Overrides the default URL for a post or page. Useful when you want a custom slug that differs from the filename. Use a text field. If not set, Jekyll generates the URL from the filename and your global permalink setting in _config.yml.
{ "name": "permalink", "type": "text" }categories and tags
Jekyll supports both. The difference: categories affect the post URL by default (unless you override with permalink), while tags do not. Both accept arrays in YAML syntax. In md0, use a text field. The editor writes comma-separated values that Jekyll parses as a list.
--- categories: [tutorial, ruby] tags: [jekyll, static-site, github-pages] ---
date
Jekyll reads the date from the filename for posts in _posts/. You can also override it via the date front matter field. md0 provides a date picker for this field and writes the value in ISO 8601 format (2026-01-15 09:00:00 +0000), which Jekyll accepts.
Templates
Liquid Templates Are Unaffected
md0 only touches your content files: the markdown posts in _posts/, _pages/, and your custom collections. Your Liquid template files in _layouts/ and _includes/ are never modified.
Example Liquid template reading front matter
---
layout: default
---
<article>
<header>
<h1>{{ page.title }}</h1>
<time datetime="{{ page.date | date_to_xmlschema }}">
{{ page.date | date: "%B %-d, %Y" }}
</time>
{% if page.categories %}
<ul class="categories">
{% for category in page.categories %}
<li>{{ category }}</li>
{% endfor %}
</ul>
{% endif %}
</header>
<div class="content">
{{ content }}
</div>
</article>The {{ page.title }}, {{ page.date }}, and {{ page.categories }} variables come from your front matter. md0 writes those front matter values. Jekyll reads them at build time and injects them into the template. The process is the same whether a human edited the file or md0 committed it.
What About Liquid in Content Files?
If you use Liquid tags inside your markdown content body (for example {% include figure.html %}), md0 treats these as plain text and preserves them exactly. md0 does not process Liquid. The visual editor shows the raw Liquid tag as text, and when the file is committed and Jekyll builds, Jekyll processes it normally.
Step 4
Check Your _config.yml
You do not need to edit _config.yml to use md0. But checking a few settings before you start helps avoid surprises.
Check Your Permalink Format
Jekyll's default permalink format affects how post URLs are generated. If you have a custom format set, posts created by md0 will follow the same URL pattern automatically because Jekyll derives URLs from filenames and front matter, not from md0.
Common permalink formats in _config.yml
# Default Jekyll permalink permalink: /:year/:month/:day/:title/ # Or a custom format permalink: /blog/:title/ # Or pretty URLs (no .html extension) permalink: pretty
Collections Configuration
If you use custom Jekyll collections, they must be declared in _config.yml under the collections key. md0 reads the files in these directories, but Jekyll needs the declaration to process them at build time.
_config.yml - full collections example
title: My Site
description: A Jekyll site managed with md0 CMS
baseurl: ""
url: "https://yoursite.com"
permalink: /blog/:title/
collections:
projects:
output: true
permalink: /projects/:name/
team:
output: false
defaults:
- scope:
path: ""
type: posts
values:
layout: post
- scope:
path: ""
type: projects
values:
layout: projectThe defaults block sets default front matter for each content type. If you set a default layout here, editors do not need to specify it every time in md0. You can still include it as a field for override capability.
Step 5
Deploy After Editing
md0 commits directly to your GitHub repo. Every deployment platform that watches your repo picks up the commit automatically. No webhook setup needed on the md0 side.
GitHub Pages
If you deploy with GitHub Pages, every push to your deployment branch triggers a Jekyll build. The md0 commit fires this build just like any other commit. New content goes live in about 30 to 60 seconds.
GitHub Pages uses Jekyll natively. You do not need to add a GitHub Actions workflow unless you use Jekyll plugins that GitHub Pages does not support by default.
Netlify and Vercel
Both platforms watch your GitHub repo for pushes and trigger a build automatically. Your build command is typically jekyll build or bundle exec jekyll build, and your publish directory is _site.
Netlify build settings
Build command: bundle exec jekyll build Publish directory: _site
The Full Publish Flow
Troubleshooting
Common Issues
Post is not appearing on the site
Check three things. First, confirm the file is in _posts/ with a valid date-prefix in the name. Jekyll silently ignores files that do not match the YYYY-MM-DD-slug.md format.
Second, check that published is not set to false in the front matter.
Third, check that the post date is not in the future. Jekyll excludes future-dated posts from the build by default. Override this with future: true in _config.yml.
Custom collection content is not building
The collection must be declared in _config.yml with output: true for Jekyll to generate individual pages for it. md0 can write files to any directory, but Jekyll only processes collections that are declared. Check your collections configuration.
Images are not loading
Set your md0 media upload path to assets/images or wherever your Jekyll theme expects images. Reference them in markdown as  or simply  if your baseurl is empty.
Build fails with a gem error
This is a Jekyll dependency issue, not an md0 issue. md0 only edits markdown files and front matter. It does not touch your Gemfile or any Ruby files. Check your build logs for which gem is failing and update it independently of md0.
Compatibility
Works With
GitHub Pages
The most common Jekyll deployment target. Every md0 save triggers a push to your GitHub repo, which triggers GitHub Pages to rebuild and deploy. No extra configuration needed.
Netlify and Vercel
Both platforms watch your GitHub repo and rebuild on every push. md0 commits trigger rebuilds the same way manual git pushes do. Build command: bundle exec jekyll build. Publish directory: _site.
Jekyll Themes
md0 works with any Jekyll theme including Minima, Chirpy, Minimal Mistakes, and custom themes. The theme controls layout and styling. md0 controls content. No conflicts.
Jekyll Plugins
md0 does not interfere with Jekyll plugins. Plugins run at build time on your server or CI environment. md0 only commits files before the build runs.
Keep Going
Next Steps
Learn the Visual Editor
md0's visual markdown editor outputs standard GitHub-flavored markdown. Editors get formatting controls, image uploads, and a live preview without ever seeing raw markdown syntax.
Visual markdown editor →Use md0 with Other Static Site Generators
md0 works with any static site generator that reads markdown from a Git repo.
Comparing Your Options?
- Migrating from Netlify CMS? See the comparison →
- Comparing md0 to Forestry? See all alternatives →
CONNECT YOUR
JEKYLL REPO
Free for public repositories. No Ruby gem installs. No config file changes. Set up in under five minutes.
CONNECT YOUR JEKYLL REPO