v0.1.0-alpha.11

Config options

See Configuration guide for how config files are merged.

Option Default
debug false shows errors with stack traces
panel true enables the panel at /panel
contentFolder "content" relative to the project dir or absolute
siteFolder "site" relative to the project dir or absolute
content.optimizeImages false converts all local images of rendered pages to AVIF, see Images
content.allowPHP false executes php files in the content folder (page.php, {slug}.php): true, or ["edit" => [...]] to also let these roles or users (email or name) edit them in the panel, see Page php files
markdown.extra false Markdown Extra for md(), textarea and writer fields: tables, footnotes, definition lists, fenced code blocks with attributes, {#id .class}, abbreviations; otherwise plain Markdown
csp false the Content-Security-Policy header of rendered pages, opt-in: true or an array of directives, see below

Custom options are allowed: App::instance()->config->get("my.option").

Content Security Policy

Rendered pages get no Content-Security-Policy header unless csp is set. "csp" => true sends the default policy below. An array maps directives to their sources and is merged over the defaults, so a project only lists the directives it changes; false removes a directive, true adds one without sources:

return [
    "csp" => [
        "script-src" => "'self' https://cdn.jsdelivr.net",
        "frame-src" => false,
        "upgrade-insecure-requests" => true,
    ],
];

The default policy allows scripts, styles, fonts and requests only from the site itself (styles also inline), images from the site, data: and https:, media from the site and https:, frames of YouTube (youtube-nocookie.com) and Vimeo for the video block, no plugins (object-src 'none'), and framing only by the site itself:

default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;
media-src 'self' https:; frame-src https://www.youtube-nocookie.com https://player.vimeo.com;
object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'

Inline scripts need the nonce of the request: <script nonce="<?= csp_nonce() ?>">…</script> (it is added to script-src). Event handler attributes (onclick="…") are blocked. The panel has its own, stricter policy (it can't be framed). Static sites built with static:build don't get the header, their web server has to send it.