Skip to content
HisarBlok
Menu
TR

HisarBlok · documentation

Themes

A theme is a folder in `themes/`. It overrides only the templates it ships; everything else comes from its parent. A one-file theme is perfectly valid.

All docs

For version 0.13.1.

The shipped themes

default

The token-driven base theme. Light and dark mode, print styles, reduced motion, visible focus, a mobile menu that needs no script.

Studio

Extends default. For software products: boxed feature grids, a window frame for screenshots, a sticky header, release notes that stand out. This site runs on Studio.

Journal

Extends default. For writing meant to be read: a serif reading column (60–70 characters a line), pull quotes, footnotes, reading time, an author box and related posts.

The folder and theme.json

themes/mytheme/
  theme.json      required: name, version, author, licence
  site.css        optional: published to the site on every build
  layout.php      optional: any of the templates below
  block-hero.php

A theme with "extends": "default" (or any installed theme) in its theme.json ships only what differs: the parent's site.css is published first and yours after it in the same file, so a visitor still loads one stylesheet. hisarblok make:theme <name> writes a child theme to start from. The theme is chosen per site on the admin's Themes screen.

Templates never touch the database

A template receives one variable: $m, the view model prepared for it. There is no database connection and no global to reach for. This is deliberate: a theme cannot write SQL and cannot open a query inside a loop, so the two most common ways to make a site slow are structurally unavailable. The lookup order for every template: active theme → its parent → the module that owns the template → default theme.

CSS variables

The cheapest possible theme redefines a few variables and ships nothing else:

:root{
  --hb-accent: #b1003c;
  --hb-radius: 4px;
  --hb-font: Georgia, serif;
}

Colour (--hb-bg, --hb-fg, --hb-accent …), shape (--hb-radius, --hb-gap, --hb-text for the reading column) and type (--hb-font, --hb-size, the heading scale) all have a dark-mode value. Fonts are system stacks; nothing is fetched from anywhere. A theme that wants its own face ships the font file in its folder, with its licence.

CSS in the page

Only the parts of the theme stylesheet a page uses are written into the page, so the browser starts drawing without waiting for a second file. Module sections are marked with @part, and a part comes along only when the page has one of its classes.

Rules

  • Never print author input unescaped. Core escapes everything before it reaches you; print anything you compose yourself through h().
  • Do not query the database. There is no connection to reach. If a template needs data it does not have, that is a missing model key.
  • Hide the honeypot: the .hb-trap rule is required. Every visitor form carries a hidden trap field. On pages drawn live only the theme's stylesheet hides it; a theme that forgets the rule shows people an empty box. A child of default inherits the rule.
  • One h1. Every page has exactly one h1: from the hero, the author's first heading or the page title.
  • A sticky header must not cover the focus. A theme that makes the header sticky sets --hb-top-sticky: 1 and its real height; the browser then scrolls a focused element or an anchor target below the header.
  • Right to left. The shipped themes use logical CSS properties (margin-inline-*, text-align:start); an Arabic or Hebrew page turns the right way by itself.
  • Themes are PHP and therefore run code. Install a third-party theme with the same care as any other software, and read what you install.

Stability

During 0.x the view model only grows: keys may be added, and will not be removed or renamed without a major version. The contract freezes at 1.0.