Configuring “sculpin_kernel.yml”: A Developer’s Reference

Datum

This page documents every key accepted by sculpin_kernel.yml – the file that configures Sculpin’s bundles, the pieces of functionality the kernel wires up before it can read a single source file.

A site’s day-to-day behaviour (titles, permalink patterns for a single post, taxonomy values) lives in front matter or in sculpin_site.yml instead. Sculpin itself is a static site generator built on PHP and Symfony components.

This reference covers the Sculpin 3.x series, the current stable line as of the sculpin/sculpin release history. A 4.0 alpha exists but is not covered here.

File location and role

Sculpin expects a fixed project layout. sculpin_kernel.yml sits in app/config alongside the site metadata files:

|-- app/
|  |-- SculpinKernel.php           # Custom Sculpin kernel
|  `-- config/
|     |-- sculpin_kernel.yml       # Sculpin's configuration (optional)
|     |-- sculpin_site.yml         # Site meta data
|     `-- sculpin_site_${env}.yml  # Env specific meta data
|-- output_${env}/                 # Env specific generated files
|-- source/                        # Files that get read and compiled
`-- composer.json                  # Dependencies

sculpin_kernel.yml versus sculpin_site.yml

Both files sit in app/config, but they answer different questions.

File Answers Environment-aware?
sculpin_site.yml What is true about the site itself: title, base URL, custom variables for templates Yes, via a matching sculpin_site_${env}.yml that is merged in with an imports directive
sculpin_kernel.yml Which bundles are configured and how: permalink strategy, ignored files, themes, content types, services Yes: app/config/sculpin_kernel_${env}.yml is loaded instead of sculpin_kernel.yml when it exists for the active environment. Only one of the two is ever loaded, never both

The distinction matters because bundle configuration, in Sculpin’s own words, is „where very advanced configuration will happen for things that are not controllable by content in the source/ folder“ (Configuration).

Before either file is read, Sculpin loads its own built-in defaults (the source of the default posts type further down this page). Source in code: AbstractKernel::registerContainerConfiguration().

Registering a bundle first

A key only does something in sculpin_kernel.yml if the bundle that defines it has been registered. Registration happens in PHP, not YAML, in app/SculpinKernel.php:

<?php

use Mavimo\Sculpin\Bundle\RedirectBundle\SculpinRedirectBundle;
use Sculpin\Bundle\SculpinBundle\HttpKernel\AbstractKernel;

class SculpinKernel extends AbstractKernel
{
    protected function getAdditionalSculpinBundles(): array
    {
        return [
            SculpinRedirectBundle::class,
        ];
    }
}

Return the class name as a string, never an instance and never a keyed array (Extending Sculpin: Configuration). Sculpin’s own core bundles (the ones behind the sculpin, sculpin_theme and sculpin_content_types keys below) are registered by default and need no such entry.

Top-level keys

Key Provided by Purpose
sculpin Sculpin core bundle Permalink strategy, source/output directories, ignored/excluded/raw file patterns
sculpin_theme Theme bundle Named theme to load from source/themes
sculpin_content_types Content Types bundle Definition of posts and any custom content type
services Symfony’s service container Ad hoc service and event-subscriber registration
sculpin_<name> Third-party bundles Bundle-specific settings, see below

The sculpin key

This is the core bundle’s own namespace.

permalink
The default permalink pattern applied to every source unless overridden in its own front matter.
ignore
An array of glob-style patterns for files that should never be read as sources at all.
exclude
An array of glob-style patterns for files that, like ignore, never become sources, but with one difference: when a matched file changes, Sculpin marks every other source as changed too, forcing a full regeneration. Useful for a shared file (a Sass partial, a data file) that several pages depend on without being a source itself.
raw
An array of glob-style patterns for files that should be read as sources but copied through unprocessed, skipping Markdown, Textile or Twig handling.
source_dir
Where Sculpin reads sources from. Defaults to %sculpin.project_dir%/source.
output_dir
Where the generated site is written. Defaults to %sculpin.project_dir%/output_%kernel.environment%, so a dev build and a prod build never collide.
sculpin:
    permalink: pretty

sculpin:
    ignore: ["**/*~"]

Source in code: the schema for all six keys is SculpinBundle’s Configuration class. The ignore / exclude / raw behaviour described above is implemented in FilesystemDataSource::refresh(), wired up with services.xml.

Permalink styles

Style Behaviour Example
none Uses the source pathname as-is source/about.html becomes about.html
date Turns a leading date in the filename into folders source/2014-04-10-article.html becomes 2014/04/10/article.html
pretty Appends index.html so the URL has no extension source/about.html becomes about/index.html

A permalink can also be a custom pattern built from tags:

Tag Meaning
:year Four-digit year
:yr Two-digit year
:month Two-digit month
:mo Month without leading zero
:day Two-digit day
:dy Day without leading zero
:title Slugified title
:slug_title Slug, or slugified title if no slug is set
:filename The source filename
:slug_filename Slug, or filename if no slug is set
:basename Filename without extension
:basename_real Filename including extension
:folder The subfolder a source lives in, if any (type folders such as _posts are stripped)
sculpin:
    permalink: blog/:year/:month/:day/:slug_title

A trailing slash in the pattern produces a trailing slash in the generated URL as well as an index.html file on disk. Source: Configuration. All three fixed styles and every tag substitution above are implemented in one place: SourcePermalinkFactory::generatePermalinkPathname(), the single best starting point for tracing exactly how a given source ends up at a given URL.

The sculpin_theme key

Themes bundle layouts, views and assets under source/themes. Support for this bundle has been stable since early 2014 but is still documented as experimental, so treat the API as subject to change.

theme
The vendor/name path of the theme to load, resolved under source/themes.
directory
The base directory themes are resolved from. Defaults to %sculpin.source_dir%/%sculpin_theme.project_dir% and rarely needs to change.
sculpin_theme:
    theme: myApp/myTheme

Asset resolution checks source/ first, then the theme directory, then any parent theme declared in a theme.yml file inside the theme folder itself (parent: 'myApp/parentTheme'). Template code reaches theme assets with the theme_path() Twig helper, for example {{ theme_path("css/style.css") }}. Source: Themes.

Source in code: both keys are declared in ThemeBundle’s Configuration class, and the theme.yml / parent lookup happens in ThemeRegistry::findActiveTheme().

The sculpin_content_types key

Each top-level key under sculpin_content_types names a content type. posts is the one built-in type, enabled for every project by default:

sculpin_content_types:
    posts:
        type: path
        path: _posts
        permalink: pretty
        taxonomies:
            - tags
            - categories

Override only what you need to change, for example the permalink:

sculpin_content_types:
    posts:
        permalink: blog/:year/:month/:day/:filename/

or disable the type outright:

sculpin_content_types:
    posts:
        enabled: false

Source: Posts. This exact block, verbatim, is Sculpin’s own built-in default, loaded before your project’s sculpin_kernel.yml and overridden by anything you place under sculpin_content_types.posts: SculpinBundle/Resources/config/kernel.yml.

A key from an older Sculpin version, sculpin_posts, still exists as a bundle but now does nothing except fail: any use of it raises an InvalidConfigurationException pointing at sculpin_content_types instead. If a tutorial or blog post you find while researching this still refers to sculpin_posts, it predates that change. Source in code: SculpinPostsExtension::load().

Type configuration keys

singular_name
The singular form of the type name. Defaults to a singularised version of the type name.
type
Either path (sources are located by directory) or meta (sources are located by a front matter value).
path
Used when type: path. The directory to scan, relative to source/. Defaults to the type name with an underscore prefix, so a type named talks defaults to _talks.
meta_key
Used when type: meta. The front matter key checked on every source. Defaults to type.
meta
Used when type: meta. The value that front matter key must hold to match this type. Defaults to the singularised type name.
publish_drafts
Whether draft sources of this type are published. Defaults to false in the prod environment and true otherwise.
layout
The default layout template for this type. Defaults to the singularised type name.
permalink
The default permalink pattern for this type.
enabled
Whether the type is active at all. Defaults to true.
taxonomies
A list of taxonomy names (such as tags) to generate proxy data providers and index pages for. Each entry can also be an array with a strategies list, though this is not covered by the official documentation.

Source: Custom Types. The full schema for these nine keys is declared in ContentTypesBundle’s Configuration class. Every default mentioned above (the _<type> path, the type meta key, the environment-dependent publish_drafts, the singular-name fallback for layout) is applied in SculpinContentTypesExtension::load().

Generating the YAML with content:create

The content:create command writes out a starting configuration block plus placeholder templates:

vendor/bin/sculpin content:create -b -t tags projects

produces:

sculpin_content_types:
    projects:
        type: path
        path: _projects
        singular_name: project
        layout: project
        enabled: true
        permalink: projects/:title
        taxonomies:
            - tags

The command prints this block to the console; it still has to be copied into sculpin_kernel.yml by hand. Source: Custom Types.

What a content type produces

Given a type named projects, the bundle wires up, among other things, a projects data provider (with next_project / previous_project metadata on each item), a projects_tags taxonomy data provider, and a projects_tag_index generator that creates one page per tag. Source: Custom Types. The data provider and, inside the taxonomies loop, the per-taxonomy provider and index generator are both built in SculpinContentTypesExtension::load().

The services key

Because sculpin_kernel.yml is loaded by Symfony’s dependency injection container, it accepts a plain services section like any Symfony application config, not only the bundle-specific keys above. This is how a project registers its own event subscribers without writing a full bundle:

services:
    skip_sources:
        class: SculpinTools\SkipSources
        arguments:
            - ["components/*", "_css/*", "_js/*"]
        tags:
            - { name: kernel.event_subscriber }

The kernel.event_subscriber tag makes Symfony call the class’s getSubscribedEvents() method and register it for whichever Sculpin lifecycle events it listens for. Source: How to make Sculpin skip certain sources, Matthias Noback.

A services block does not have to live inside sculpin_kernel.yml at all. If a file named app/config/sculpin_services.yml exists, Sculpin loads it automatically, before sculpin_kernel.yml and with no imports directive needed, which is a convenient place to keep service definitions separate from bundle configuration. Source in code: AbstractKernel::buildContainer().

Bundles can define their own dependency injection tags for the same services key. The CommonMark bundle, for instance, lets a project register an extension class under its own tag:

services:
    league.commonmark.tablextension:
        class: League\CommonMark\Extension\Table\TableExtension
        tags:
            - { name: sculpin_commonmark.extension }

Source: sculpin-commonmark-bundle.

Third-party bundle namespaces

Once a bundle is registered in SculpinKernel.php, it typically exposes its own top-level key in sculpin_kernel.yml. A few published examples:

Bundle Key Notable options
sculpin-less-bundle sculpin_less extensions, files (a files whitelist takes precedence over the extensions whitelist)
sculpin-scss-bundle sculpin_scss formatter_class (defaults to the compressed scssphp formatter), extensions, files
sculpin-commonmark-bundle none of its own; extended through services Exposes services such as sculpin_commonmark.environment and the sculpin_commonmark.extension tag

Example for the SCSS bundle:

sculpin_scss:
    formatter_class: 'Leafo\ScssPhp\Formatter\Compressed'
    extensions: ["scss"]
    files: ["assets/css/style.scss"]

All three bundles also rely on the core sculpin.ignore key to keep their unprocessed source files (partials, imports) out of the generated site:

sculpin:
    ignore: ["assets/css/_imports/"]

A composite example

Pulling the namespaces above into one file:

sculpin:
    permalink: pretty
    ignore: ["**/*~", "assets/css/_imports/"]

sculpin_theme:
    theme: myApp/myTheme

sculpin_content_types:
    posts:
        permalink: blog/:year/:month/:day/:filename/
    projects:
        type: path
        path: _projects
        singular_name: project
        layout: project
        permalink: projects/:title
        taxonomies:
            - tags

sculpin_scss:
    extensions: ["scss"]
    files: ["assets/css/style.scss"]

services:
    skip_sources:
        class: SculpinTools\SkipSources
        arguments:
            - ["components/*"]
        tags:
            - { name: kernel.event_subscriber }

Where to look in the source

A quick map from each fact on this page to the exact class or file that implements it, all pinned to commit bff3efa of sculpin/sculpin so the line numbers stay accurate:

Topic Class / file Lines
sculpin schema SculpinBundle Configuration 27-39
ignore / exclude / raw behaviour FilesystemDataSource 132-185
Permalink styles and tags SourcePermalinkFactory 81-163
sculpin_kernel.yml / sculpin_kernel_${env}.yml load order, sculpin_services.yml autoload AbstractKernel 88-97, 122-126
sculpin_theme schema ThemeBundle Configuration 27-40
Theme parent inheritance ThemeRegistry 59-82
Built-in default posts type SculpinBundle/Resources/config/kernel.yml 1-8
sculpin_content_types schema ContentTypesBundle Configuration 38-84
Content type defaults and wiring SculpinContentTypesExtension 44-268
Legacy sculpin_posts key (now an error) SculpinPostsExtension 28-39

The src/Sculpin/Bundle directory is the fastest way to explore further: every bundle mentioned on this page, and several not covered here (Markdown, Pagination, Twig, Textile), follows the same pattern of a DependencyInjection/Configuration.php for the YAML schema and an Extension.php for what that configuration actually does.

Sources

  1. Configuration — sculpin.io
  2. Basic Project — sculpin.io
  3. Themes — sculpin.io
  4. Content Types: Posts — sculpin.io
  5. Content Types: Custom Types — sculpin.io
  6. Extending Sculpin: Configuration — sculpin.io
  7. Extending Sculpin: Creating Bundles — sculpin.io
  8. Extending Sculpin: Community Extensions — sculpin.io
  9. sculpin-less-bundle — bcremer, GitHub
  10. sculpin-scss-bundle — devworks, GitHub
  11. sculpin-commonmark-bundle — bcremer, GitHub
  12. sculpin/sculpin source code (commit bff3efa) — sculpin, GitHub
  13. How to make Sculpin skip certain sources — Matthias Noback
  14. Releases: sculpin/sculpin — sculpin, GitHub

License

This document is © Robert Wetzlmayr and licensed under Creative Commons Attribution-ShareAlike 4.0 International. Reuse, adaptation and redistribution are welcome, including commercially, as long as attribution is given and any adapted version carries the same license. Sculpin itself, and the bundles referenced above, remain under their own MIT licenses; this notice covers the text and structure of this page only, not the software it describes.

Fork me!


Kategorien Sculpin