All site-wide configuration lives in config/config.php. This file is loaded at the very start of every request. A copy called config-example.php is included in the repository as a safe starting point — copy it to config.php before making changes.
Core Settings
$enableHTMLCacheServe
Type: bool | Default: false
Enables the server-side HTML cache. When true, rendered pages are saved as static .html files and served directly on subsequent requests until the cache expires.
Set to false during development so you always see your latest changes. Enable it for production to improve performance.
$enableHTMLCacheServe = false;
See the Caching page for full details.
$SSL
Type: bool | Default: false
Tells the framework whether the site is served over HTTPS. Setting this to true causes all internally constructed URLs to use the https:// protocol and triggers a redirect if the visitor arrives over HTTP.
$SSL = true;
$ForceWWW
Type: bool | Default: true
When true, the framework redirects any request that does not include www. to the www. version of the URL (and vice versa when false). This keeps your canonical URL consistent.
$ForceWWW = true;
$WebsiteURL
Type: string
Your domain name, without a protocol prefix and without a trailing slash. The framework combines this with $SSL and $ForceWWW to construct the full canonical URL used in redirects and meta tags.
$WebsiteURL = "example.com";
Site Identity
$WebsiteTitle
Type: string
The name of your site. Appears in browser tab titles (appended after the page title), OpenGraph og:site_name, and the hero banner in the skeleton theme.
$WebsiteTitle = "My Website";
$WebsiteDescription
Type: string
The default meta description for any page that does not define its own pageexcerpt. Also used as the OpenGraph description fallback.
$WebsiteDescription = "A short description of my website.";
$WebsiteAuthor
Type: string
The default author name used in the tag for any page that does not define its own pageauthor.
$WebsiteAuthor = "Jane Smith";
$WebsiteKeywords
Type: string
A comma-separated list of default keywords used in for pages that do not define their own pagekeywords.
$WebsiteKeywords = "website, framework, php, simple";
$WebsiteImage
Type: string
Path to the default image (relative to the site root) used in the OpenGraph og:image tag for pages that do not define their own pageimage. Also used as the default image in the RSS feed.
$WebsiteImage = "images/my-default-image.webp";
Language & Locale
$WebsiteLanguage
Type: string | Example: "en"
The primary language code used in the attribute.
$WebsiteLanguageCountry
Type: string | Example: "US"
The country code used in a secondary lang attribute.
$WebsiteLanguageLocale
Type: string | Example: "en_US"
The locale string used in the OpenGraph og:locale tag.
$WebsiteLanguage = "en";
$WebsiteLanguageCountry = "US";
$WebsiteLanguageLocale = "en_US";
Theme
$theme
Type: string | Default: "skeleton"
The name of the active theme. Must match a folder name inside themes/. Changing this value switches the entire site to a different theme.
$theme = "skeleton";
$showhomepagetitle
Type: bool | Default: true
Controls whether the page title <h1> is shown on the home page. On all other pages the title is always shown. Set to false if your home page design handles the heading itself.
$showhomepagetitle = true;
Plugins
$loadplugins
Type: bool | Default: true
Master switch for the plugin system. When false, plugins/plugins.php is never included and no plugin code runs — including jQuery. Set to false only if you are certain you need nothing from the plugin system.
$loadplugins = true;
$jQuery
Type: bool | Default: true
Loads jQuery 3.7.1 and jQuery Migrate 3.4.0. Setting this to false will break any plugin or page script that depends on jQuery, including the StellarNav navigation system.
$anchorLinkAutoClass
Type: bool | Default: true
Adds the CSS class anchor-top-margin to every anchor link on the page via JavaScript. This is used to apply scroll-margin-top so that anchor targets are not hidden behind the sticky navigation bar. Disabling this will break smooth scroll behaviour.
$anchorLinkCurrentURLRewrite
Type: bool | Default: true
Rewrites all href="#..." anchor links so they include the full current page URL (e.g. /about#section instead of just #section). This is required for anchor links to work correctly when the framework handles routing through index.php. Disabling this will break all in-page anchor links.
$metaInfoBoxRewriteURL
Type: bool | Default: true
When the ?meta=yes debug overlay is active, this option appends ?meta=yes to every link on the page so you can browse the site without losing the overlay. Only activates when ?meta=yes is present in the URL; has no effect otherwise.
$fontAwesome
Type: bool | Default: true
Loads Font Awesome 4.7.0. Set to false if you are not using Font Awesome icons and want to reduce page weight.
$yBox
Type: bool | Default: true
Loads the yBox lightbox plugin. Required if you want clickable image lightboxes on your pages.
Editor Plugin
$editorEnabled
Type: bool | Default: false
Master switch for the optional browser-based page editor. When false, zero editor code runs anywhere on the site and the ?editor query parameter is ignored entirely. See the Editor page for full setup instructions.
$editorEnabled = false;
$editorToken
Type: string
A secret string that must be present in the URL for the editor to appear at all. Anyone without the token sees nothing — not even a login form. Should be a long random string. Generate one with:
php -r "echo bin2hex(random_bytes(16));"
$editorToken = 'a3f8c2d1e4b7906f2a1d3c5e7b9f0d2e';
$editorPasswordHash
Type: string
A bcrypt hash of the editor password. Never store the plaintext password — generate the hash once and paste the result here. See the Editor page for step-by-step instructions on generating the hash.
$editorPasswordHash = '$2y$10$...';
$editorTotpSecret
Type: string | Default: '' (two-factor disabled)
Optional two-factor authentication for the editor. When set, the login form asks for a six-digit code from an authenticator app in addition to the password. Left as an empty string, two-factor is off and the editor behaves exactly as it does without this setting — no code field, nothing else to configure.
No third-party service is involved. Your authenticator app and the server each hold the same secret and each compute the same code from the current time; nothing is exchanged over the network.
The value must be Base32 — the letters A–Z and the digits 2–7 only. A passphrase will not work, because authenticator apps decode what you type as Base32 before hashing it. Do not invent a value by hand; generate one from the editor's enrolment screen, which also gives you a QR code to scan and lets you verify a code before you commit:
https://yoursite.com/about?editor=yourtoken&totp=setup
$editorTotpSecret = 'LL2ITCZZLBF4UVYMCOQDTYXUJIFPCNCD';
If the configured value is not valid Base32, the editor refuses to run and says so, rather than silently rejecting every code you type.
This secret cannot be hashed. Unlike $editorPasswordHash, the server needs the real value in order to recompute codes, so it is stored here in plain text. Make sure config/.htaccess is in place denying web access to this directory, and keep a copy of the secret somewhere safe — if you lose your phone, the only way back in is to blank this value over FTP or SSH.
See the Editor page for the full walkthrough.
$editorSessionTimeout
Type: int | Default: 1800
How long an authenticated editor session lasts without activity, in seconds. After this period the session expires and the password must be entered again — along with a code, if two-factor is enabled.
$editorSessionTimeout = 1800; // 30 minutes