PHPackages                             rokde/laravel-pergament - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. rokde/laravel-pergament

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

rokde/laravel-pergament
=======================

A file-based CMS package for Laravel with documentation, blog, landing pages, SEO, and PWA support.

v1.2.2(1mo ago)1185↓15%[3 issues](https://github.com/rokde/laravel-pergament/issues)[1 PRs](https://github.com/rokde/laravel-pergament/pulls)MITPHPPHP ^8.4CI passing

Since Feb 20Pushed 2mo agoCompare

[ Source](https://github.com/rokde/laravel-pergament)[ Packagist](https://packagist.org/packages/rokde/laravel-pergament)[ Fund](https://www.buymeacoffee.com/robertkummer)[ Fund](https://www.paypal.me/rok)[ RSS](/packages/rokde-laravel-pergament/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (9)Dependencies (14)Versions (14)Used By (0)

Laravel Pergament
=================

[](#laravel-pergament)

[![Latest Version on Packagist](https://camo.githubusercontent.com/d59f8074143192adb1f70f29bb9e49da8d6aa59fb19cdd5ee991ab6ed8711808/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f6b64652f6c61726176656c2d70657267616d656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/rokde/laravel-pergament)[![GitHub Tests Action Status](https://camo.githubusercontent.com/e64a04a812d5272d13b916f7b1ec2af866a1b1fcc2189bb9d94e574b83ae4360/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f726f6b64652f6c61726176656c2d70657267616d656e742f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/rokde/laravel-pergament/actions/workflows/tests.yml?query=branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/555b5c0d889e868085880d989066de0033c781980a7145b296ee299145ca5408/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726f6b64652f6c61726176656c2d70657267616d656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/rokde/laravel-pergament)

A file-based CMS package for Laravel. Renders documentation, blog posts, and standalone pages from Markdown files with YAML front matter. Blade templates, Tailwind CSS, dark mode, server-side syntax highlighting — no database required.

Installation
------------

[](#installation)

Add the package via Composer:

```
composer require rokde/laravel-pergament
```

Publish the configuration:

```
php artisan vendor:publish --tag=pergament-config
```

Publish the views (optional, for customization):

```
php artisan vendor:publish --tag=pergament-views
```

Publish only the header component (navigation bar, search, font controls, dark mode toggle):

```
php artisan vendor:publish --tag=pergament-header
```

Publish only the footer component (copyright bar):

```
php artisan vendor:publish --tag=pergament-footer
```

Configuration
-------------

[](#configuration)

The main config file is `config/pergament.php`. Key options:

### Base URL Prefix

[](#base-url-prefix)

Control where Pergament listens. All routes are nested under this prefix:

```
'prefix' => '/',                    // Pergament owns the root
'prefix' => 'docs',                 // Pergament lives at /docs/*
'prefix' => 'landing-page/hello',   // Pergament lives at /landing-page/hello/*
```

### Content Path

[](#content-path)

Where your Markdown content lives on disk:

```
'content_path' => base_path('content'),
```

### Homepage

[](#homepage)

Configure what shows at the base URL:

```
'homepage' => [
    'type' => 'page',        // "page", "blog-index", "doc-page", or "redirect"
    'source' => 'home',      // page slug, "chapter/page", or redirect target
],
```

### Documentation

[](#documentation)

```
'docs' => [
    'enabled' => true,
    'path' => 'docs',            // subfolder under content_path
    'url_prefix' => 'docs',      // URL segment: /prefix/docs/chapter/page
    'title' => 'Documentation',
],
```

### Blog

[](#blog)

```
'blog' => [
    'enabled' => true,
    'path' => 'blog',
    'url_prefix' => 'blog',
    'title' => 'Blog',
    'per_page' => 12,
    'default_authors' => [],
    'feed' => [
        'enabled' => true,
        'type' => 'atom',        // "atom" or "rss"
        'title' => null,
        'description' => '',
        'limit' => 20,
    ],
],
```

### Colors &amp; Theming

[](#colors--theming)

Configure your brand color and page background. Both values propagate as CSS custom properties (`--p-primary`, `--p-bg`) that drive the entire UI — navigation highlights, badges, links, scrollbars, focus rings, text selection, and more:

```
'colors' => [
    'primary'    => '#3b82f6',   // any CSS color: hex, oklch, named…
    'background' => '#ffffff',
],
```

Dark mode is handled automatically: the background switches to a dark slate (`#111827`) and tints derived from `--p-primary` re-resolve against it without any extra configuration.

### Site &amp; SEO

[](#site--seo)

```
'site' => [
    'name' => env('APP_NAME', 'Pergament'),
    'url' => env('APP_URL', 'http://localhost'),
    'locale' => 'en',
    'seo' => [
        'title' => env('APP_NAME', 'Pergament'),
        'description' => '',
        'keywords' => '',
        'og_image' => '',
        'twitter_card' => 'summary_large_image',
        'robots' => 'index, follow',
    ],
],
```

### Text-to-Speech

[](#text-to-speech)

Add a play/pause button that reads page content aloud using the browser's [Speech Synthesis API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis). Each content type can be enabled independently:

```
'tts' => [
    'blog'  => true,            // show on blog posts
    'docs'  => true,            // show on documentation pages
    'pages' => false,           // show on standalone pages
    'voice' => 'Samantha',      // preferred voice name (null = browser default)
    'rate'  => 1.0,             // speech rate: 0.5 (slow) to 2.0 (fast)
],
```

The `voice` value is browser- and OS-dependent. Common options:

PlatformVoicesmacOS / iOS`Samantha`, `Alex`, `Daniel`, `Karen`, `Moira`, `Thomas`Chrome`Google UK English Female`, `Google UK English Male`, `Google US English`Windows`Microsoft David`, `Microsoft Zira`, `Microsoft Mark`If the chosen voice is unavailable, the browser's default voice is used as fallback.

Content Structure
-----------------

[](#content-structure)

```
content/
├── docs/
│   ├── 0-getting-started/
│   │   ├── 01-introduction.md
│   │   └── 02-installation.md
│   └── 1-configuration/
│       └── 01-basic-setup.md
├── blog/
│   ├── 2024-01-15-hello-world/
│   │   ├── post.md
│   │   └── hero.png
│   └── 2024-03-20-new-feature/
│       └── post.md
└── pages/
    ├── home.md
    ├── about.md
    └── pricing.md

```

### Documentation

[](#documentation-1)

Documentation lives in numbered chapter directories. Each chapter contains numbered Markdown files:

- Directory format: `{order}-{chapter-slug}/` (e.g. `0-getting-started/`)
- File format: `{order}-{page-slug}.md` (e.g. `01-introduction.md`)
- The numeric prefixes control sort order and are stripped from URLs

### Blog Posts

[](#blog-posts)

Blog posts live in date-prefixed directories:

- Directory format: `{YYYY-MM-DD}-{slug}/` (e.g. `2024-01-15-hello-world/`)
- Each directory contains a `post.md` file and any associated media files
- The date is extracted from the directory name

### Standalone Pages

[](#standalone-pages)

Simple Markdown files in the `pages/` directory. The filename (without `.md`) becomes the URL slug.

Front Matter
------------

[](#front-matter)

All content files use YAML front matter delimited by `---`:

```
---
title: My Page Title
excerpt: A brief description shown on index pages
---

# My Page Title

Content goes here.
```

### Documentation Front Matter

[](#documentation-front-matter)

```
---
title: Introduction
excerpt: Getting started with Pergament
---
```

### Blog Post Front Matter

[](#blog-post-front-matter)

```
---
title: "Hello World"
excerpt: "Our very first blog post"
category: "Announcements"
tags:
  - "laravel"
  - "pergament"
author: "Jane Doe"
---
```

You can also define multiple authors with details:

```
authors:
  - name: "Jane Doe"
    email: "jane@example.com"
    url: "https://janedoe.com"
    avatar: "https://example.com/avatar.jpg"
  - name: "John Smith"
```

### Page Front Matter

[](#page-front-matter)

```
---
title: About Us
excerpt: Learn more about our company
layout: landing
---
```

Set `layout: landing` to use the full-width landing page layout instead of the default centered content layout.

### SEO Overrides

[](#seo-overrides)

Any page can override global SEO settings using dot notation in its front matter:

```
---
title: My Page
seo.title: "Custom SEO Title - My Site"
seo.description: "A custom meta description for this specific page"
seo.og_image: "https://example.com/special-og.png"
seo.robots: "noindex, nofollow"
---
```

These override the corresponding values from `config('pergament.site.seo.*')`.

GitHub-Style Alerts
-------------------

[](#github-style-alerts)

Pergament supports GitHub-style alert blocks for highlighting important information. Alerts are enabled by default.

### Syntax

[](#syntax)

```
> [!NOTE]
> Useful information that users should know, even when skimming.

> [!TIP]
> Helpful advice for doing things better or more easily.

> [!IMPORTANT]
> Key information users need to know to achieve their goal.

> [!WARNING]
> Urgent info that needs immediate user attention to avoid problems.

> [!CAUTION]
> Advises about risks or negative outcomes of certain actions.
```

### Alert Types

[](#alert-types)

TypePurposeColor`NOTE`Supplementary informationBlue`TIP`Helpful adviceGreen`IMPORTANT`Key informationPurple`WARNING`Urgent noticesAmber`CAUTION`Risk warningsRedEach alert renders as a styled `` with an icon, title, and content. Dark mode variants are included automatically.

### Configuration

[](#configuration-1)

```
'markdown' => [
    'alerts' => true,   // set to false to disable alert rendering
],
```

When disabled, alert syntax is rendered as a plain blockquote.

Footnotes
---------

[](#footnotes)

Pergament supports inline footnotes via the CommonMark `FootnoteExtension`. Footnotes are disabled by default.

### Syntax

[](#syntax-1)

```
Here is a sentence with a footnote.[^1]

You can have multiple footnotes[^2] in a single document[^3].

[^1]: This is the first footnote.
[^2]: This is the second footnote.
[^3]: Footnotes can contain **Markdown** formatting.
```

Footnote references render as superscript links (``) that anchor to the footnote list at the bottom of the page. Each footnote includes a backlink to return to the reference in the text.

### Configuration

[](#configuration-2)

```
'markdown' => [
    'footnotes' => false,   // set to true to enable footnote support
],
```

Block-Based Landing Pages
-------------------------

[](#block-based-landing-pages)

For landing pages and homepages, you can use block directives in Markdown to create structured sections. Block directives wrap content in `` elements with CSS classes for styling.

### Syntax

[](#syntax-2)

```
:::hero

# Welcome to Our Product

The best solution for your needs.

[Get Started](/docs/getting-started/introduction)

:::

:::features

## Why Choose Us

- **Fast** — Built for speed
- **Reliable** — 99.9% uptime
- **Simple** — Easy to use

:::

:::cta

## Ready to Get Started?

Sign up today and see the difference.

[Sign Up Free](/register)

:::
```

Each `:::{name}` block becomes a `` in the rendered HTML. The closing `:::` ends the block.

### Built-in Block Types

[](#built-in-block-types)

The default views include basic styles for these block types:

DirectiveCSS ClassPurpose`:::hero``pergament-block-hero`Hero sections with centered text`:::features``pergament-block-features`Feature grids and lists`:::cta``pergament-block-cta`Call-to-action sectionsYou can use any name — it maps directly to a CSS class. Custom blocks like `:::pricing`, `:::testimonials`, or `:::team` will generate `pergament-block-pricing`, `pergament-block-testimonials`, and `pergament-block-team` classes respectively.

### Styling Blocks

[](#styling-blocks)

Override the default styles by publishing the views and editing the CSS, or add your own styles targeting the generated classes:

```
.pergament-block-hero {
    padding: 6rem 2rem;
    text-align: center;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
}

.pergament-block-features {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2rem;
    padding: 4rem 2rem;
}

.pergament-block-pricing {
    /* your custom block styles */
}
```

### Full Landing Page Example

[](#full-landing-page-example)

Create `content/pages/home.md`:

```
---
title: "My Product"
layout: landing
seo.title: "My Product - The Best Solution"
seo.description: "Discover the best solution for your needs"
---

:::hero

# My Product

Build something amazing with our platform.

[Get Started](/docs/getting-started/introduction) [Learn More](#features)

:::

:::features

## Features

### Lightning Fast
Our platform is optimized for performance at every level.

### Fully Extensible
Plugin system lets you customize everything.

### Dark Mode
Beautiful light and dark themes out of the box.

:::

:::cta

## Start Building Today

Join thousands of developers who trust our platform.

[Sign Up Free](/register)

:::
```

Then set the homepage config to use it:

```
'homepage' => [
    'type' => 'page',
    'source' => 'home',
],
```

Dark Mode
---------

[](#dark-mode)

The package supports class-based dark mode. Add the `dark` class to your `` element to activate dark mode. All views include `dark:` Tailwind variants.

### Themed Images

[](#themed-images)

Documentation images can have dark/light variants that automatically switch based on the active theme. Place variant files alongside the original:

```
content/docs/0-getting-started/
├── 01-introduction.md
├── dashboard.png           # referenced in markdown
├── dashboard.dark.png      # shown in dark mode
└── dashboard.light.png     # shown in light mode (optional)

```

The variant resolution works as follows:

Dark variant existsLight variant existsLight mode showsDark mode showsNoNo`dashboard.png``dashboard.png`YesNo`dashboard.png``dashboard.dark.png`NoYes`dashboard.light.png``dashboard.png`YesYes`dashboard.light.png``dashboard.dark.png`Command Palette Search
----------------------

[](#command-palette-search)

When search is enabled, a command palette is available on every page. Open it with `Cmd+K` (macOS) or `Ctrl+K` (other platforms), or by clicking the search input in the navigation bar.

- **Real-time results** — results appear as you type, fetched from the search endpoint as JSON (no page reload)
- **Type badges** — each result is labelled **Doc**, **Post**, or **Page**
- **Keyboard navigation** — `↑`/`↓` to move between results, `Enter` to open, `Escape` to close
- **Mouse navigation** — click any result to navigate
- **Excerpt preview** — a short excerpt is shown below each title; falls back to the first 160 characters of content when no explicit excerpt is set in front matter
- **No-JS fallback** — the nav search form submits to `/search?q=…` as before when JavaScript is unavailable

Search covers all three content types:

TypeSourceDocDocumentation pagesPostBlog postsPageStandalone pagesBlade Components
----------------

[](#blade-components)

The header and footer are extracted as anonymous Blade components so you can publish and customise them independently without overriding the entire view set.

### Header (``)

[](#header-x-pergamentheader-)

The header component renders the sticky navigation bar and includes:

- Site name / logo link
- Documentation and Blog navigation links (shown when the respective feature is enabled)
- Search input (shown when search is enabled)
- Font-size controls (A− / A+ / OpenDyslexic toggle)
- Dark mode toggle
- Mobile hamburger menu with all of the above
- Command palette overlay (shown when search is enabled)

Publish just the header to customise it:

```
php artisan vendor:publish --tag=pergament-header
```

This publishes `resources/views/vendor/pergament/components/header.blade.php` into your application. Laravel's view resolution automatically prefers the published file over the package default.

### Footer (``)

[](#footer-x-pergamentfooter-)

The footer component renders the bottom bar containing the copyright notice.

Publish just the footer to customise it:

```
php artisan vendor:publish --tag=pergament-footer
```

This publishes `resources/views/vendor/pergament/components/footer.blade.php` into your application.

> Both components are also included when you run `php artisan vendor:publish --tag=pergament-views`.

Artisan Commands
----------------

[](#artisan-commands)

### Create a documentation page

[](#create-a-documentation-page)

We have an interactive docs creation command. All arguments are optional, you will be guided through all necessary things.

```
php artisan pergament:make:doc

# Or with arguments
php artisan pergament:make:doc --chapter=getting-started --title="Installation Guide" --order=02
```

### Create a blog post

[](#create-a-blog-post)

```
php artisan pergament:make:post

# Or with arguments
php artisan pergament:make:post \
    --title="My First Post" \
    --category="Tutorials" \
    --tags="laravel, php" \
    --author="Jane Doe" \
    --date=2024-06-15
```

Both commands prompt for any missing arguments interactively.

Routes
------

[](#routes)

All routes are nested under the configured `prefix`. With the default `/` prefix:

RouteDescription`/`Homepage`/docs`Documentation index (redirects to first page)`/docs/{chapter}/{page}`Documentation page`/blog`Blog index`/blog/{slug}`Blog post`/blog/category/{category}`Posts by category`/blog/tag/{tag}`Posts by tag`/blog/author/{author}`Posts by author`/blog/feed`RSS/Atom feed`/search?q=query`Search`/{slug}`Standalone page`/sitemap.xml`XML sitemap`/robots.txt`Robots.txt`/llms.txt`LLMs.txtWith `prefix` set to `docs`, all routes become `/docs/...`, `/docs/blog/...`, etc.

Markdown Responses for AI &amp; LLMs
------------------------------------

[](#markdown-responses-for-ai--llms)

All content pages (documentation, blog posts, standalone pages, and the homepage) can be served as plain Markdown instead of HTML. This is configurable in the exports section of the configuration.

A markdown response is returned when any of the following is true:

TriggerExample`Accept: text/markdown` request header`curl -H "Accept: text/markdown" /docs/getting-started/installation`Known AI / LLM user-agentRequests from ChatGPT, Claude, Perplexity, etc.`.md` URL suffix`/blog/my-post.md`Media files, feeds, sitemaps, and search results are excluded — only rendered HTML content pages are converted.

Features
--------

[](#features)

- **File-based content** — Markdown + YAML front matter, no database
- **Documentation** — Numbered chapters/pages, sidebar navigation, TOC scrollspy, heading anchor links, themed images
- **Blog** — Categories, tags, multiple authors, date-prefixed directories, pagination
- **RSS/Atom feeds** — Configurable feed type and limits
- **SEO** — Meta tags, Open Graph, Twitter Cards, per-page overrides via dot notation
- **Sitemap** — Auto-generated XML sitemap
- **robots.txt / llms.txt** — Auto-generated or custom content
- **Markdown responses** — All content pages served as plain Markdown via `Accept: text/markdown`, `.md` suffix, or known AI user-agents (powered by spatie/laravel-markdown-response)
- **Command palette search** — `Cmd+K`/`Ctrl+K` opens a live search dialog across docs, posts, and pages; keyboard navigable; no-JS form fallback
- **PWA** — Optional manifest.json and service worker
- **GitHub-style alerts** — `> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!WARNING]`, `> [!CAUTION]` blocks with icons and color coding; dark mode included
- **Footnotes** — Inline `[^ref]` syntax with superscript links and back-references; opt-in via config
- **Landing pages** — Block-based content with `:::directive` syntax
- **Dark mode** — Class-based toggle with system preference detection; dark-mode syntax highlighting
- **Syntax highlighting** — Server-side via tempest/highlight, light and dark themes included
- **Theming** — Configure `colors.primary` and `colors.background`; the entire UI (nav, links, badges, scrollbars, focus rings, text selection) derives from these two values via CSS custom properties
- **Zoomable images** — Click any image to enlarge it in a lightbox; Escape or click outside to close
- **Copy code** — Hover a code block to reveal a Copy button; switches to "Copied" on success
- **Text-to-speech** — Optional play/pause button that reads content aloud using the browser Speech Synthesis API; configurable per content type, with selectable voice and speech rate
- **Configurable prefix** — Mount the CMS at any URL path

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](./.github/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Robert Kummer](https://github.com/rokde)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance69

Regular maintenance activity

Popularity17

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 97.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

12

Last Release

45d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/4946056?v=4)[Robert Kummer](/maintainers/rokde)[@rokde](https://github.com/rokde)

---

Top Contributors

[![rokde](https://avatars.githubusercontent.com/u/4946056?v=4)](https://github.com/rokde "rokde (46 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

laraveldocumentationmarkdowncmsblogpergament

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/rokde-laravel-pergament/health.svg)

```
[![Health](https://phpackages.com/badges/rokde-laravel-pergament/health.svg)](https://phpackages.com/packages/rokde-laravel-pergament)
```

###  Alternatives

[dniccum/nova-documentation

A Laravel Nova tool that allows you to add markdown-based documentation to your administrator's dashboard.

37116.4k](/packages/dniccum-nova-documentation)[grazulex/laravel-atlas

Laravel Atlas scans your Laravel project to generate a complete, structured map of its internal components — models, controllers, routes, jobs, observers, events, commands, and more — and exports visual or machine-readable representations in formats like Mermaid, Markdown, JSON, or PDF.

161.7k](/packages/grazulex-laravel-atlas)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
