dempe/scabbard

Artisan commands for generating a static site based on Blade templates

v1.0.21 2025-07-18 19:54 UTC

README

Scabbard is a minimalist static site generator (SSG) built on top of Laravel and Blade. It provides a zero-dependency workflow for generating static sites from your Laravel views.

Features:

  • File watching – Monitors specified directories for changes
  • Static builds – Outputs your site to a target directory (output/ by default)
  • Hot rebuilding – Rebuilds automagically when changes are detected
  • Local server – Serves the site locally on the port of your choice

All built in pure PHP.

Just run:

php artisan scabbard:serve

And you're off to the races!

Installation

composer require dempe/scabbard --dev
php artisan vendor:publish --tag=scabbard-config

Scabbard requires a Laravel 10 or 11 installation. Composer will install the necessary illuminate/* packages that match your framework version.

Configuration

Configs are in config/scabbard.php.

Directory-based Routing

Scabbard assumes directory-based routing so a request like /blog/my-post will load the file blog/my-post/index.html. Define your routes to point at index.html within each directory:

'routes' => [
    '/blog/my-post' => 'blog/my-post/index.html',
],

This keeps URLs free of .html extensions for cleaner SEO‑friendly links.

Directories to Watch

These directories trigger a new build if they're updated while you're running the server

Output Directory

Where to build the static site to (default ./output).

Directories to Copy

These are directories that are copied wholesale into your configured output directory. The default is simple ./public.

Routes to Render

This is a mapping of routes (defined in your app's routes/web.php) to their filenames in your configured output directory.

Dynamic Routes

Dynamic routes allow generating multiple pages from a single route pattern. Define dynamic_routes in your scabbard.php config with a mapping of the route pattern to an array containing the output path pattern and a callback that returns the values for the placeholders. For example:

'dynamic_routes' => [
    '/posts/{slug}' => [
        'output' => '/posts/{slug}/index.html',
        'values' => 'App\\Models\\Post@slug',
    ],
],

Specify the model class and attribute to pluck using the Class@attribute notation. During the build, Scabbard will pluck the attribute values (e.g., App\Models\Post::pluck('slug');) and use each one to replace the {slug} placeholder, producing both the request URI and the output file path.

Server Port

The port your server runs on (default 8000).

404 Page

Path to the 404 page relative to your output directory. This is served when no matching file is found while running scabbard:serve (default /404.html).

Additional Commands

Build

If you don't want to run the server, you can just produce the static output.

This builds the site once and exits:

php artisan scabbard:build

Use the --watch flag to enable hot rebuilds without running a server:

php artisan scabbard:build --watch

Static Analysis

This project uses PHPStan for static code analysis. Run:

composer phpstan

to analyze the codebase.

Notes

  • Works with Laravel 10 and above.
  • Scabbard does not require JavaScript, npm, or Node.js.
  • You can use any Blade features you normally would in Laravel.

Roadmap

  • Markdown parsing
  • Frontmatter parsing
  • Syntax highlighting
  • Deployment