rokde / laravel-pergament
A file-based CMS package for Laravel with documentation, blog, landing pages, SEO, and PWA support.
Fund package maintenance!
www.paypal.me/rok
Buy Me A Coffee
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 1
pkg:composer/rokde/laravel-pergament
Requires
- php: ^8.4
- illuminate/support: ^11.0|^12.0
- league/commonmark: ^2.0
- tempest/highlight: ^2.0
Requires (Dev)
- laravel/pint: ^1.27
- orchestra/testbench: ^10.0
- pestphp/pest: ^3.0|^4.0
This package is auto-updated.
Last update: 2026-02-15 18:22:21 UTC
README
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
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
Configuration
The main config file is config/pergament.php. Key options:
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
Where your Markdown content lives on disk:
'content_path' => base_path('content'),
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
'docs' => [ 'enabled' => true, 'path' => 'docs', // subfolder under content_path 'url_prefix' => 'docs', // URL segment: /prefix/docs/chapter/page 'title' => 'Documentation', ],
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, ], ],
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', ], ],
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 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 live in date-prefixed directories:
- Directory format:
{YYYY-MM-DD}-{slug}/(e.g.2024-01-15-hello-world/) - Each directory contains a
post.mdfile and any associated media files - The date is extracted from the directory name
Standalone Pages
Simple Markdown files in the pages/ directory. The filename (without .md) becomes the URL slug.
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
--- title: Introduction excerpt: Getting started with Pergament ---
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
--- 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
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.*').
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 <div> elements with CSS classes for styling.
Syntax
:::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 <div class="pergament-block pergament-block-{name}"> in the rendered HTML. The closing ::: ends the block.
Built-in Block Types
The default views include basic styles for these block types:
| Directive | CSS Class | Purpose |
|---|---|---|
:::hero |
pergament-block-hero |
Hero sections with centered text |
:::features |
pergament-block-features |
Feature grids and lists |
:::cta |
pergament-block-cta |
Call-to-action sections |
You 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
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
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
The package supports class-based dark mode. Add the dark class to your <html> element to activate dark mode. All views include dark: Tailwind variants.
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 exists | Light variant exists | Light mode shows | Dark mode shows |
|---|---|---|---|
| No | No | dashboard.png |
dashboard.png |
| Yes | No | dashboard.png |
dashboard.dark.png |
| No | Yes | dashboard.light.png |
dashboard.png |
| Yes | Yes | dashboard.light.png |
dashboard.dark.png |
Artisan Commands
Create a documentation page
php artisan pergament:make-doc-page # Or with arguments php artisan pergament:make-doc-page getting-started installation --title="Installation Guide" --order=02
Create a blog post
php artisan pergament:make-blog-post # Or with arguments php artisan pergament:make-blog-post my-first-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
All routes are nested under the configured prefix. With the default / prefix:
| Route | Description |
|---|---|
/ |
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.txt |
With prefix set to docs, all routes become /docs/..., /docs/blog/..., etc.
Features
- File-based content — Markdown + YAML front matter, no database
- Documentation — Numbered chapters/pages, sidebar navigation, previous/next 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
- Search — Full-text search across docs and blog
- PWA — Optional manifest.json and service worker
- Landing pages — Block-based content with
:::directivesyntax - Dark mode — Class-based, themed image variants
- Syntax highlighting — Server-side via tempest/highlight
- Configurable prefix — Mount the CMS at any URL path
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.