Shape the site
Assets and static files
Files that aren’t pages go in assets/, for templates to link to, or in
static/, to be published exactly as they are.
Which folder?
assets/ |
static/ |
|
|---|---|---|
| What goes in it | Files templates link to: stylesheets, Sass, scripts, fonts. | Files that must keep their name and address, such as .well-known/security.txt or a worker’s script. |
| What Statac does | Builds Sass into CSS, and names each file by what it holds. | Nothing: each file is published as it is. |
| Where it is published | At the top of the site, with a mark in its name: assets/site.css at /site.1a2b3c4d.css. |
At the same path from the top of the site: static/.well-known/security.txt at /.well-known/security.txt. |
| How a page links to it | With css(), js() or asset() in a template. |
By its address. In a template, url() keeps it inside the site. |
The mark in an asset’s name changes whenever a byte of the file does, so a browser can keep the file for as long as the host lets it.
A new site’s static/favicon.ico is published at /favicon.ico, where
browsers look for the icon they show in a site’s tab.
Link a file from a template
{{ css("site.css") }}
{{ js("app.js") }}
<link rel="preload" href="{{ asset('fonts/font-1.woff2') }}" as="font" crossorigin>
| Function | Writes |
|---|---|
css("site.css") |
The stylesheet’s <link>. |
js("app.js") |
The script’s <script>: see scripts. |
asset("fonts/font-1.woff2") |
The file’s address, for a tag you write yourself. |
Each takes the file’s path inside assets/.
Stylesheets
In assets/site.css:
@font-face {
font-family: "Font 1";
src: url("fonts/font-1.woff2") format("woff2");
}
An address in a stylesheet that names another file in assets/, in
url(...) or @import, is written as that file’s published name.
In assets/ |
Statac |
|---|---|
site.scss or site.sass |
Builds it into site.css, linked as css("site.css"). |
A Sass file whose name starts with _, such as _parts.scss |
Publishes it only as part of the stylesheets that use it. |
For another CSS tool, make it a command of your own that
writes its stylesheet into assets/ before each build.
The code stylesheet
{{ css("code.css") }}
Each build publishes code.css, a stylesheet Statac writes with the
colours for code: code blocks,
files shown as code, and the
highlight filter. Link it in the layout’s
<head>.
code_style in statac.yaml chooses the colours:
code_style |
The colours |
|---|---|
ocean |
Base16 Ocean: muted blues, greens and reds. The default. |
gruvbox |
Gruvbox: warm and retro. |
solarized |
Solarized. |
catppuccin |
Catppuccin: Latte in the light, Mocha in the dark. |
one-half |
One Half. |
Each style is a light look and its dark twin, and the reader’s own
setting chooses between them. Where an element around the code carries
data-theme="light" or data-theme="dark", as a site’s own switch might
set on <html>, that look is kept whatever the reader’s setting.
A colour too faint to read on its background is written a little darker,
or lighter in the dark look, to give a contrast of 4.5 to 1. The classes
on the code follow code_style, so a stylesheet written for one style
doesn’t fit another.
Each style brings a background for the code. The stylesheet
statac new writes puts the code on the page’s own surface
instead:
pre.code,
figure.code {
background: var(--surface);
}
On that surface two styles fall a little under 4.5 to 1 in the light
look: solarized at 4.31 to 1 and one-half at 4.16 to 1. Remove the
three lines and each style has its own background back.
An assets/code.css of your own takes the place of Statac’s. To start
from Statac’s, copy the one in the built site, named with its mark, such
as _site/code.7d70e732.css, into assets/ as code.css.
A stylesheet for maths
In assets/maths.css, beside a copy of mathmlfixes.css:
@import "mathmlfixes.css";
@font-face {
font-family: "Libertinus Math";
src: url("fonts/LibertinusMath-Regular.woff2") format("woff2");
font-display: swap;
}
math {
font-family: "Libertinus Math", math;
/* The patched font's raised primes. */
font-feature-settings: "ss09";
}
Statac builds maths as MathML and adds nothing else for it. Without a maths font of the site’s own, a browser uses the system’s, which differs from one computer to the next. Two files put that right:
- A maths font in
assets/, such as Libertinus Math from the patched math-core-fonts, made for MathML in browsers. mathmlfixes.css, published with math-core, the library Statac builds maths with. It evens out how browsers space a matrix’s cells and draw\cancel,\boxedand accents.
A template loads the stylesheet only on pages whose writing holds maths:
{% if page.maths %}{{ css("maths.css") }}{% endif %}
Scripts
{{ js("app.js") }}
A script in assets/ is published as written, under its marked name.
js() reads it to tell which kind it is:
| The script | js() writes |
|---|---|
A module: it has an import or export statement, or import.meta |
<script type="module" src="/app.01c5c780.js"></script> |
| Any other script | <script src="/plain.95a7d502.js" defer></script> |
Modules and the import map
In assets/app.js:
import { one } from "./lib.js";
Modules import each other by their own names. On a page where js()
places a module, or a script that loads one with import(...), Statac
writes an import map before it, sending the name of every script in
assets/ to its published one:
<script type="importmap">
{
"imports": {
"/app.js": "/app.01c5c780.js",
"/lib.js": "/lib.574cb057.js"
}
}
</script>
Warning:
A browser reads the import map on the page, never inside a worker.
Keep a worker, and the files it imports, in static/.
What JavaScript does the site carry?
JavaScript the site carries:
`/app.01c5c780.js` from `assets/app.js`, on 1 page
Statac never puts JavaScript on a page unasked: the one <script> a
build adds is the import map, which holds no code.
Serve adds a script to each page it sends, to reload
it, and never writes it into a file.
statac check lists the JavaScript the site carries after the problems
it shows.
| On a page | statac check lists it |
|---|---|
A script from assets/, placed with js() |
By its address and file, as above. |
JavaScript written in a template, in a page’s own HTML, or in a piece of the writing under snippets/markdown/ |
By its file: Written in `templates/base.html`, on 12 pages. |
| A script loaded from another site, or anything embedded that may run a script of its own | By its address. |
| What a snippet called by name holds, written out whole in its file | Not at all: calling a snippet is choosing what its file holds. |
JavaScript a snippet is handed, or an address it fills in as the page is built, such as <script src="{{ address }}"> |
By the file that wrote it. |
The starter’s two snippets for videos kept on other sites each hold a script, so a site that calls them is told nothing of it.
Where next?
- Templates: where
css(),js()andasset()are written, and what a template sees - Commands of your own: run a CSS tool, or any other step, before each build
- Writing: code blocks, and the maths a page can hold
- Building and publishing: what
statac checkshows
Something unclear or wrong? Open an issue on GitHub.