mdcms/README.md

4.4 KiB

MD-CMS

Markdown-based static site publishing — no server, no database, no terminal required.

MD-CMS lets you write and publish a website entirely in markdown. Drop your .md files in a folder, run the build tool, upload the output to any static host, and you're done. All rendering happens in the browser.


How it works

MD-CMS has two parts:

index.html — a single-file browser renderer. It reads your markdown files, config, and navigation at runtime and renders everything client-side. No build pipeline, no framework, no compilation step.

mdcms.py — a zero-dependency Python CLI tool. It scans your content, generates nav.yml and search.json, validates your config, and packages everything into a zip file ready for upload.


Features

  • Write in markdown — pages and posts with YAML frontmatter
  • Categories — serve multiple versions of the same page (e.g. languages, destinations, variants) via ?cat= URL parameter and a dropdown UI
  • Sections — nested navigation defined in nav.yml; pages declare their section via frontmatter
  • Full-text search — category-aware, generated at build time
  • Dynamic content tags — embed post lists with date sorting, pagination, and year grouping using fenced mdcms code blocks
  • RTL support — per-category text direction
  • Custom fonts per category — load a font file from assets/fonts/ when a category is selected
  • Light and dark mode — fully themeable via config.yml
  • No server required — everything is static; deploy to GitHub Pages, Codeberg Pages, Cloudflare Pages, Netlify, or any file host
  • Zero dependenciesmdcms.py uses only the Python standard library

File structure

mdcms.py          ← build tool, run this
quickstart.md     ← getting started guide
website/          ← everything in here gets deployed
  index.html
  config.yml
  nav.yml
  search.json
  pages/
    home.md
    about.md
    about.nb.md   ← Norwegian variant of about.md
  posts/
    2025-01-01-my-first-post.md
  assets/
    images/
    fonts/

The website/ folder is your deployable site. mdcms.py lives outside it.


Getting started

Requirements: Python 3 (standard library only). A modern browser.

  1. Clone or download this repository.
  2. Run python3 mdcms.py and choose option 2 to build your config and folder structure from scratch.
  3. Write your pages in website/pages/ and posts in website/posts/.
  4. Run mdcms.py again and choose option 3 to generate nav.yml and search.json.
  5. Choose option 8 to start a local webserver and preview your site.
  6. When ready to publish, choose option 1 to validate, build, and export website.zip.
  7. Upload the contents of website.zip to your static host.

Local preview note: Open index.html via the built-in webserver (option 8), not by double-clicking the file. Browsers block local file access due to CORS restrictions.


Configuration

Site behaviour is controlled by two YAML files in website/:

config.yml — site title, logo, default page, search settings, typography, layout dimensions, light/dark theme colours, and category definitions.

nav.yml — navigation structure. Sections are defined here; pages declare their section via section-id in frontmatter. Sections can be nested.

Both files are human-readable and comment-supported. The mdcms.py wizard generates them for you and can fill in missing values interactively.


Categories

Categories let you publish multiple versions of the same page — different languages, regions, or product variants — under a single URL with a ?cat= parameter.

Each variant is a separate file:

about.md          ← default
about.en-gb.md    ← British English variant
about.nb.md       ← Norwegian variant

The category dropdown shows only categories for which a variant exists (or where a "not available" message is configured). All internal links preserve the active category.


Tag system

Embed dynamic post lists in any page using fenced mdcms code blocks:

```mdcms
posts-date-reversechronological
limit: 10
paginate: yes
```

Available tags cover chronological and reverse-chronological post lists, grouped by year, with date or datetime display, and configurable pagination.


Licence

Apache 2.0 — see LICENCE.

© Kristian Benestad