---
url: /en/docs/frameworks/middleman.md
description: >-
  Learn how to integrate Sveltia CMS with Middleman, including the admin page
  setup, blog collection configuration and real-world examples.
---

# Middleman Integration Guide

This guide provides resources and information for integrating Sveltia CMS with [Middleman](https://middlemanapp.com/), a static site generator using Ruby.

## Examples

See real-world examples of Middleman integrations in our [Showcase](/en/showcase?framework=middleman). Most of the listed sites include links to their source code, so you can explore how they implemented Sveltia CMS with Middleman.

## Setup

### Adding the Admin Page

All the files that make up a Middleman site live in the [`source` folder](https://middlemanapp.com/basics/directory-structure/). Create `source/admin/index.html` and `source/admin/config.yml` as described in the [Getting Started](/en/docs/start#manual-installation) guide.

Middleman applies the site [layout](https://middlemanapp.com/basics/layouts/) to every HTML file in the `source` folder, which would break the admin page. Turn off the layout for the admin folder in `config.rb`:

```ruby [config.rb]
page '/admin/*', layout: false
```

The admin page is then available at `/admin/` on the development server started with `middleman server` as well as on the built site.

## Configuration

Blog posts are usually managed with the [middleman-blog](https://middlemanapp.com/basics/blogging/) extension. Its `sources` option defines the file name pattern for posts, which includes the post date by default:

```ruby [config.rb]
activate :blog do |blog|
  blog.prefix = 'blog'
  blog.sources = '{year}-{month}-{day}-{title}.html'
end
```

With this configuration, posts are stored in `source/blog` with names like `2026-10-01-hello-world.html.md`. The matching Sveltia CMS entry collection needs three options to follow the pattern:

* `slug` creates the date prefix from the [slug template tags](/en/docs/collections/entries/slugs#slug-template-tags) `{{year}}`, `{{month}}` and `{{day}}`, which are based on the entry creation date.
* `extension` is set to `html.md`, because Middleman uses the double extension to determine the output format (`html`) and the template engine (Markdown).
* `format` is set to `frontmatter` so the files are read as Markdown with front matter despite the custom extension.

```yaml [source/admin/config.yml]
media_folder: source/images/uploads
public_folder: /images/uploads
collections:
  - name: blog
    label: Blog
    folder: source/blog
    slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
    extension: html.md
    format: frontmatter
    create: true
    fields:
      - { name: title, label: Title }
      - { name: tags, label: Tags, widget: list, required: false }
      - { name: published, label: Published, widget: boolean, default: true }
      - { name: body, label: Body, widget: markdown }
```

`title` is the only required front matter property in middleman-blog, and posts with `published: false` are treated as drafts that only appear on the development server.

The post date is taken from the file name. If you also want editors to set the date, add a DateTime field named `date` and build the slug from it with the [`date` transformation](/en/docs/string-transformations#date), so the file name follows the selected date instead of the creation date:

```yaml
slug: "{{date | date('YYYY-MM-DD')}}-{{slug}}"
```

Keep in mind that middleman-blog stops the build if the date in the front matter doesn’t match the one in the file name. The file name is set when a post is first saved, so if an editor changes the date of an existing post, they also need to update the date in the slug from the [Slug panel](/en/docs/ui/content-editor#slug-panel), which renames the file.
