PHPackages                             jreisdorf/kirby-static-site-generator - 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. jreisdorf/kirby-static-site-generator

ActiveKirby-plugin

jreisdorf/kirby-static-site-generator
=====================================

Static site generator plugin for Kirby 3, 4 and 5

2.3.3(5mo ago)201.8k4[1 issues](https://github.com/jonathan-reisdorf/kirby-static-site-generator/issues)MITPHP

Since May 1Pushed 5mo ago4 watchersCompare

[ Source](https://github.com/jonathan-reisdorf/kirby-static-site-generator)[ Packagist](https://packagist.org/packages/jreisdorf/kirby-static-site-generator)[ RSS](/packages/jreisdorf-kirby-static-site-generator/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (1)Versions (12)Used By (0)

Kirby 3 / 4 / 5 - Static Site Generator
=======================================

[](#kirby-3--4--5---static-site-generator)

[![License](https://camo.githubusercontent.com/850eae1099d2b05f53383473d7cd51f9bc1ab09b7d0d9e5122f1dd930efdcc6d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6d6173686170652f6170697374617475732e737667)](https://camo.githubusercontent.com/850eae1099d2b05f53383473d7cd51f9bc1ab09b7d0d9e5122f1dd930efdcc6d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6d6173686170652f6170697374617475732e737667) [![Kirby 3](https://camo.githubusercontent.com/f06d505d5d4d514f4b7e492613c648caa608f102ca9cdace291f8e13cf8c5125/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d332d626c61636b2e737667)](https://camo.githubusercontent.com/f06d505d5d4d514f4b7e492613c648caa608f102ca9cdace291f8e13cf8c5125/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d332d626c61636b2e737667) [![Kirby 4](https://camo.githubusercontent.com/178aae908ca38a3ea6ece74d37269a84e5a71d4fa582d199b29f011aa1ed46bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d342d626c61636b2e737667)](https://camo.githubusercontent.com/178aae908ca38a3ea6ece74d37269a84e5a71d4fa582d199b29f011aa1ed46bf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d342d626c61636b2e737667) [![Kirby 5](https://camo.githubusercontent.com/89607758cbcd8c50ac3e45e9cd39d497e8addb148898f3256b03bcc346cb219c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d352d626c61636b2e737667)](https://camo.githubusercontent.com/89607758cbcd8c50ac3e45e9cd39d497e8addb148898f3256b03bcc346cb219c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4b697262792d352d626c61636b2e737667)

With this plugin you can create a directory with assets, media and static html files generated from your pages. You can simply upload the generated files to any CDN and everything (with small exceptions, see below) will still work. The result is an even faster site containing only static files (no PHP).

Example
-------

[](#example)

[![static site generator field example](example.gif)](example.gif)

What is Kirby?
--------------

[](#what-is-kirby)

[Kirby](https://getkirby.com) is a highly [customizable](https://getkirby.com/docs/guide/blueprints/introduction) and [file-based](https://getkirby.com/docs/guide/database) CMS (content management system). Before using this plugin make sure you have [installed](https://getkirby.com/docs/guide/installation) the latest version of Kirby CMS and are familiar with the [plugin basics](https://getkirby.com/docs/guide/plugins/plugin-basics).

How to install the plugin
-------------------------

[](#how-to-install-the-plugin)

If you use composer, you can install the plugin with: `composer require jreisdorf/kirby-static-site-generator`

Alternatively, create a `static-site-generator` folder in `site/plugins`, download this repository and extract its contents into the new folder.

What works
----------

[](#what-works)

- Compatibility with multilanguage sites
- Translated URLs
- Assets
- Media (also when resized; files are automatically generated and copied when used)
- Customizable base URL
- Customizable paths to copy
- Customizable output folder
- Copying plugin assets
- Preserve individual files / folders in the output folder
- Custom routes (click [here](#custom-routes) for more information)
- Custom pages filtering (click [here](#custom-filters) for more information)

What doesn't work
-----------------

[](#what-doesnt-work)

- Dynamic routes (unless when called by custom route - click [here](#custom-routes) for more information)
- Query parameters (unless processed by javascript)
- Redirections / `die` or `exit` in the code (this also affects the compatibility with some other plugins)
- Kirby paginations (only manual paginations via custom routes)
- Directly opening the html files in the browser with the file protocol (absolute base url `/`)
- Compatibility with other plugins that work with the `file::version` and `file::url` components
- Compatibility with `esc` when used for internal URLs

How to use it
-------------

[](#how-to-use-it)

### 1) Directly (e.g. from a kirby hook)

[](#1-directly-eg-from-a-kirby-hook)

```
$staticSiteGenerator = new JR\StaticSiteGenerator($kirby, $pathsToCopy = null, $pages = null);
$fileList = $staticSiteGenerator->generate($outputFolder = './static', $baseUrl = '/', $preserve = []);
```

- `$pathsToCopy`: if not given, `$kirby->roots()->assets()` is used; set to `[]` to skip copying other files than media
- `$pages`: if not given, all pages are rendered
- use `$preserve` to preserve individual files or folders in your output folder, e.g. if you want to preserve a `README.md` in your output folder, set `$preserve`to `['README.md']`; any files or folders directly in the root level and starting with `.` are always preserved (e.g. `.git`)
- The `JR\StaticSiteGenerator` class offers a couple of public methods that allow to make further configuration changes.

### 2) By triggering an endpoint

[](#2-by-triggering-an-endpoint)

To use this, adapt config option `jr.static_site_generator.endpoint` to your needs (should be a string)

### 3) By using a `static-site-generator` field

[](#3-by-using-a-static-site-generator-field)

Do the same as for option 2) and then add a `staticSiteGenerator` type field to one of your blueprints:

```
fields:
    staticSiteGenerator:
        label: Generate a static version of the site
        # ... (see "Field options")
```

### 4) By using Kirby CLI

[](#4-by-using-kirby-cli)

```
$ kirby ssg:generate
```

Available configuration options
-------------------------------

[](#available-configuration-options)

```
return [
  'jr' => [
    'static_site_generator' => [
      'endpoint' => null, # set to any string like 'generate-static-site' to use the built-in endpoint (necessary when using the blueprint field)
      'output_folder' => './static', # you can specify an absolute or relative path
      'preserve' => [], # preserve individual files / folders in the root level of the output folder (anything starting with "." is always preserved)
      'base_url' => '/', # if the static site is not mounted to the root folder of your domain, change accordingly here
      'skip_media' => false, # set to true to skip copying media files, e.g. when they are already on a CDN; combinable with 'preserve' => ['media']
      'skip_templates' => [], # ignore pages with given templates (home is always rendered)
      'custom_routes' => [], # see below for more information on custom routes
      'custom_filters' => [], # see below for more information on custom filters
      'ignore_untranslated_pages' => false, # set to true to ignore pages without an own language
      'index_file_name' => 'index.html' # you can change the directory index file name, e.g. to 'index.json' when generating an API
    ]
  ]
];
```

All of these options are only relevant if you use implementation options 2) or 3). When directly using the `JR\StaticSiteGenerator` class, no config options are required. In that case, options like `skip_media` can be achieved by calling `$staticSiteGenerator->skipMedia(true)`.

Field options
-------------

[](#field-options)

```
label: Generate static site
help: Custom help text
progress: Custom please-wait message
success: Custom success message
error: Custom error message
```

Custom routes
-------------

[](#custom-routes)

You can also use this plugin to render custom routes. This way, e.g. paginations can be created programmatically.

Custom routes are passed as an array. Each item must contain at least a `path` property and if the path does not match a route, either the `page` or `route` property must be set.

Here is an example array, showing the different configuration options:

```
$customRoutes = [
  [ // minimal configuration to render a route (must match, else skipped)
    'path' => 'my/route',
  ],
  [ // minimal configuration to render a page
    'path' => 'foo/bar',
    'page' => 'some-page-id'
  ],
  [ // advanced configuration to render a route (write to different path)
    'path' => 'sitemap.xml',
    'route' => 'my/sitemap/route'
  ],
  [ // advanced configuration to render a page
    'path' => 'foo/baz',
    'page' => page('some-page-id'),
    'languageCode' => 'en',
    'baseUrl' => '/custom-base-url/',
    'data' => [
      'foo' => 'bar'
    ]
  ]
];
```

Only `GET` routes without `language` scope are supported (you can of course add multiple custom routes for multiple languages). Patterns and action arguments are supported.

`page` is provided as a string containing the page ID, or as a page object.

If `languageCode` is not provided, the given page is rendered in the default language.

If `baseUrl` is not provided, the default base url is taken.

`path` may also end with a file name, in which case the given file is created instead of using the `/index.html` schema.

To pass custom data to the controller or template, use `data`. [Click here](https://getkirby.com/docs/guide/templates/controllers#arguments-from-page-render-in-route) for more information how to use it.

⚠️ Have a look [here](https://getkirby.com/docs/reference/system/options/ready) in case you want to dynamically generate the custom routes based on a specific page or point to pages in the config. Kirby comes with a `ready` option for this purpose.

### There are two ways to define custom routes:

[](#there-are-two-ways-to-define-custom-routes)

#### 1) Directly, when using this plugin directly

[](#1-directly-when-using-this-plugin-directly)

```
$staticSiteGenerator->setCustomRoutes($customRoutes);
```

#### 2) Via configuration, when using the endpoint or `static-site-generator` field

[](#2-via-configuration-when-using-the-endpoint-or-static-site-generator-field)

```
'jr.static_site_generator.custom_routes' => $customRoutes
```

Custom filters
--------------

[](#custom-filters)

When using the endpoint or `static-site-generator` field, this plugin will by default render all pages and subpages (using `pages()->index()`). You can filter the pages to be rendered by providing an array of custom filters in config option `custom_filters`.

```
'jr.static_site_generator.custom_filters' => $customFilters
```

Each element of this array must be an array of arguments accepted by [`$pages->filterBy()` method](https://getkirby.com/docs/cookbook/content/filtering). Here is an example array, showing some filters you could use (not exhaustive):

```
$customFilters = [
  ['slug', '==', 'foo'], // will render page if its slug is exactly 'foo'
  ['url', '!*=', 'bar'], // will render page if its url doesn't contain 'bar'
  ['uri', '*', '/[1-9]/'], // will render page if its uri match regex '/[1-9]/'
  ['depth', '>', '2'], // will render page if its depth is greater than 2
  ['category', 'bar'], // will render page if its value in 'category' field is 'bar' ('category' being a single value field)
  ['tags', 'bar', ','], // will render page if its value in 'tags' field includes 'bar' ('tags' being a field accepting a comma-separated list of values)
  ['date', 'date >', '2018-01-01'], // will render page if its date is after '2018-01-01'
];
```

⚠️ Here again, you can use [Kirby's `ready` option](https://getkirby.com/docs/reference/system/options/ready) to dynamically generate the custom filters.

Warnings
--------

[](#warnings)

Be careful when specifying the output folder, as the given path (except files starting with `.`) will be erased before the generation! There is a safety check in place to avoid accidental erasure when specifying existing, non-empty folders.

Contribute
----------

[](#contribute)

Feedback and contributions are welcome!

Please post all bug reports in our issue tracker. We have prepared a template which will make it easier to describe the bug.

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance70

Regular maintenance activity

Popularity31

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 84.6% 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 ~64 days

Recently: every ~72 days

Total

10

Last Release

162d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8958624?v=4)[Jonathan Reisdorf](/maintainers/jonathan-reisdorf)[@jonathan-reisdorf](https://github.com/jonathan-reisdorf)

---

Top Contributors

[![jonathan-reisdorf](https://avatars.githubusercontent.com/u/8958624?v=4)](https://github.com/jonathan-reisdorf "jonathan-reisdorf (11 commits)")[![bezin](https://avatars.githubusercontent.com/u/4400435?v=4)](https://github.com/bezin "bezin (1 commits)")[![thisislawatts](https://avatars.githubusercontent.com/u/472589?v=4)](https://github.com/thisislawatts "thisislawatts (1 commits)")

### Embed Badge

![Health badge](/badges/jreisdorf-kirby-static-site-generator/health.svg)

```
[![Health](https://phpackages.com/badges/jreisdorf-kirby-static-site-generator/health.svg)](https://phpackages.com/packages/jreisdorf-kirby-static-site-generator)
```

###  Alternatives

[getkirby/cms

The Kirby core

1.5k535.5k352](/packages/getkirby-cms)[distantnative/retour-for-kirby

Manage redirects and track 404s right from the Kirby CMS Panel

14689.4k1](/packages/distantnative-retour-for-kirby)[arnoson/kirby-vite

Vite helper for Kirby CMS

9759.2k3](/packages/arnoson-kirby-vite)[getkirby/staticache

Static site performance on demand

9615.4k](/packages/getkirby-staticache)[fabianmichael/kirby-meta

Your all-in-one powerhouse for any SEO and metadata needs imaginable.

6910.7k1](/packages/fabianmichael-kirby-meta)[thathoff/kirby-oauth

Kirby OAuth 2 Plugin

3823.9k](/packages/thathoff-kirby-oauth)

PHPackages © 2026

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