What it does

scriptor-markdown-pages turns a directory of .md files into frontend pages. URLs whose first segment matches a configured track slug (/developer-guide/..., /user-guide/...) resolve to markdown files under a content root, rendered with CommonMark + GFM + heading anchors and passed through Scriptor's normal template chain. It also registers a read-only Documentation module in the editor sidebar so operators can browse the content tree from the admin UI.

It is the right plugin when your content is files in a git repository rather than rows in the database: documentation sites, handbooks, anything where the deploy pipeline owns the content and authoring happens in an editor and a pull request, not the CMS. This very site runs on it.

It is the reference consumer of the Scriptor 2.1 Plugin API: it exercises PageResolving, ContentRendering, registerEditorModule, and addEditorMenuItem, every hook the API offers. If you are writing your own plugin, its source is the most complete worked example.

Install

Host install (local PHP, shared hosting). The plugin is not on Packagist, so point Composer at its VCS repository first, then require it:

composer config repositories.scriptor-markdown-pages \
  vcs https://github.com/bigin/scriptor-markdown-pages
composer require bigins/scriptor-markdown-pages:^0.1

Docker. Bake it into the image with the two build args (see Installed plugins):

services:
  scriptor:
    build:
      args:
        SCRIPTOR_PLUGIN_REPOS: "https://github.com/bigin/scriptor-markdown-pages"
        SCRIPTOR_PLUGINS:      "bigins/scriptor-markdown-pages:^0.1"

Discovery is automatic either way: Scriptor reads type: scriptor-plugin packages from installed.json at boot, so the next request picks the plugin up. No theme code changes required.

Configure

Under plugins.markdown_pages in data/settings/custom.scriptor-config.php. Every key is optional:

return [
    'plugins' => [
        'markdown_pages' => [
            'content_root'   => __DIR__ . '/../content',
            'tracks'         => ['user-guide', 'developer-guide'],
            'editor_enabled' => true,
            'editor_slug'    => 'docs',
            'editor_label'   => 'Documentation',
        ],
    ],
];
Key Default Effect
content_root <scriptor-root>/content Where the markdown tree lives.
tracks auto-discovered URL first segments the plugin claims. If omitted, every immediate subdirectory of content_root holding an _index.md becomes a track, alphabetically. Pass [] to opt out of nav contributions while keeping the plugin installed.
editor_enabled true Register the Documentation module + menu entry.
editor_slug 'docs' URL slug for the editor module.
editor_label 'Documentation' Sidebar label.

The tracks auto-discovery is worth leaning on: drop a new content/<track>/_index.md and it appears in the nav without a config edit. Maintaining a hand-written tracks array means a second source of truth that drifts when a track is renamed or removed.

Use

Lay each track out as its own directory under content_root:

content/
├── developer-guide/
│   ├── _index.md
│   ├── welcome.md
│   └── concepts/
│       ├── _index.md
│       └── life-of-a-request.md
└── user-guide/
    ├── _index.md
    └── ...

URL to file resolution:

  • /<track>/content/<track>/_index.md
  • /<track>/<a>/content/<track>/<a>.md, else content/<track>/<a>/_index.md
  • deeper segments nest the same way

Each segment is sanitised to [a-z0-9_-], so a URL can never traverse out of the content root. Keep your filenames within that set too: a dot or space in a filename produces a slug that resolves to a 404.

Every .md opens with YAML frontmatter:

---
title: "Building a Theme"
summary: "Build your first Scriptor theme from an empty directory."
---

title sets the page H1 (and the leading # Heading in the body is stripped so it is not duplicated), summary feeds the meta description, and template picks a theme template. The plugin synthesises a Page DTO with template markdown-section; a theme can supply markdown-section.php for a custom layout or let it fall through to basic.php.