Technical reference
Build a zero-JS static article site from hand-written HTML fragments.
arachnopress reads articles/slug/article.html files and builds
a single-page or multi-page static article site in site/.
make build is the normal interface.
It runs in POSIX-like BSD, Linux, and macOS environments. Generated output
is served as static files and may also be opened through
file://. It requires no server-side processing.
sh and make builds for BSD, Linux,
and macOS, with optional versioned release packaging.
Run make build from the project root. It builds every source
article and replaces site/. Supply settings through the
environment or as make command-line variables.
Do not store source files in or run make from
site/; each successful build replaces it.
The build requires a POSIX-like operating environment with
sh, make, awk, sed,
grep, sort, tr, date,
dirname, pwd,
printf, mktemp, mkdir, rm,
wc, cat, cksum,
chmod, mv, cp, and find.
The maintainer targets additionally require cmp,
tar, and gzip support in tar.
mktemp is widely available but is not specified by POSIX.
The generated interface requires browser support only for HTML and CSS.
It uses CSS :has(), :target,
prefers-color-scheme, native
details/summary, and the HTML popover API. The
optional randomised article backdrop requires CSS random();
unsupported browsers retain the SVG's base fit. The bundled backdrop uses
a centred cover fit.
build, release, and full,
their defaults, and their explicit inclusion lists.
favicon.svg,
automatic-theme rules, and embedded navigation rules in the selected
build root.
data-auto-dark and
data-auto-light pair mappings. Its IDs are reserved as page
anchors.
site/articles/ and linked from the page.
The example tree shows maintained source and make build
output. site/ contains deployed files and copied articles. The
example contains only the arachnopress article.
make build copies the configured files and articles into a
private staging tree, renders the complete site, then replaces
site/. A failure before publication preserves the previous
output.
site/ is generated output. All targets replace the same
directory and must not run concurrently. The maintainer release targets
also manage the generator download marker and versioned archive.
Each article begins with a one-line article element. Its
class list must include article. Its id must
equal the containing directory name. data-title is required.
Use double-quoted values for attributes read by the generator.
data-created and data-modified accept a value
beginning with a valid YYYY-MM-DD date or auto:
data-created: missing, empty, or auto uses
the current UTC build date.
data-modified: missing or empty uses the resolved
creation date; auto uses the build date.
data-listed defaults to true and accepts only
true or false.
SITE_MODE_UNLISTED=false excludes articles marked
data-listed=false from generated HTML and navigation in
either output mode.
SITE_MODE_UNLISTED=true enables unlisted output.
data-feed-sections selects none, h1,
h2, or h3. Unset or empty means none.
See Atom feed modes under NAVIGATION AND THEMES.
Unlisted output:
slug.html, absent from listed-page
indexes, and included only in its own index. Its document has
noindex, nofollow.
index.html and have no
separate robots directive.
site/articles/.
index.
The source header contains an h1 and summary. The build inserts
Created and a time element before its closing tag. Updated is
the newest resolved article or heading date and appears when it differs
from Created. Unlisted articles are prefixed with Unlisted; fields use
middle-dot separators.
Use h2 for major sections and h3 for genuine
subdivisions. Indexable headings contain plain text and close on the same
source line. An h3 must follow an h2. The build
preserves a valid explicit ID or derives a unique ID from the heading and
article.
Article, heading, theme, generated control, and generated block IDs share one collision registry. Explicit IDs and slugs may contain ASCII letters, digits, dots, underscores, and hyphens.
Every source h2 and h3 is indexed. IDs on other
author-supplied elements are preserved but are not registered; keep them
unique and clear of generated IDs.
Indexable headings may use data-created and
data-modified. Values follow the article-date format and may
use auto. Their resolved dates contribute to Updated metadata,
modification ordering, and Atom dates. They do not reorder section or
subsection indexes.
Generated markers are empty, file-backed elements contained on one source
line. data-src is relative to the article directory. Missing
or invalid sources render visible missing blocks. Use double-quoted
marker attributes.
File paths (data-src, SITE_ICON_PATH,
SITE_BACKGROUND_PATH):
. and .. components and symlinks are rejected.data-title: display title. data-note: header
qualifier.
data-open="false": initially closed.data-header="false": always visible, without a summary.data-footer: true or false
overrides the default. Normal blocks hide the footer for source line
counts at or below CODE_FOOTER_LINES; headerless blocks
hide it unless explicitly enabled.
Raw links and sizes refer to the original file. Only the rendered code is HTML-escaped.
A download marker names exactly one file. data-title changes
only its display title and data-note adds a qualifier. The
link continues to target data-src. The block shows the raw
size and, when a supported checksum program is available, its SHA256.
The obsolete data-downloads attribute is rejected; use one
data-src marker per file.
The generator article has exactly one marker carrying
data-release="generator". The release and full targets replace
that complete line with the validated current archive name; a normal
build leaves it unchanged.
data-alt: alternative text. data-caption:
caption.
data-title and data-note: header labels.data-open and data-header: as for code blocks.data-footer: shown with a normal header unless
false; a headerless image requires true to
show it.
data-scale caps inline size: small (20rem),
medium (32rem), large (48rem), or
full (article width, default). Images retain their aspect
ratio, do not upscale, and remain within the viewport.
data-border: full (default),
fit, or none. fit shrink-wraps
the block with one width for its header, image border, and footer.
none removes the frame, uses the opaque article
background, and suppresses both bars.
data-align: start, center
(default), or end.
Text flow:
Image viewer:
A missing or invalid source renders a missing block. A non-empty or multiline marker is fatal.
HIGHLIGHTER selects pygments,
source-highlight, or none. Use an explicit
data-lang for predictable lexer selection, or omit it for
automatic selection.
Pygments is the default. An omitted data-lang requests
filename inference. data-lang="auto" may also guess from
content.
Source-highlight uses tools/html-fragment.outlang. An omitted
or automatic language lets the program infer its input language.
A missing program, unknown lexer, failed invocation, missing output
definition, or empty highlighted result for non-empty input falls back to
escaped raw source for that block. HIGHLIGHTER=none always
uses that path.
Successful highlighted output is filtered to unwrap whitespace-only
Pygments span.w and Source-highlight
span.sh-normal elements. Their whitespace remains in the
preformatted code content.
The build writes title, creation-date, and modification-date order lists.
ARTICLE_ORDER selects the initial list; CSS radio controls
select another.
In single-page mode, URL fragments and CSS
:target/:has() select articles, sections, and
subsections. The first listed article is visible without a target.
index.html embeds the generated navigation rules.
In multi-page mode, index.html contains the first listed
article and each article has slug.html. Each file contains one
article, its section index, and its generated navigation rules. A slug
page title is its article title followed by SITE_TITLE; the
index page title is SITE_TITLE.
Title order is case-insensitive by title, then slug. Creation order uses the resolved article creation date. Modification order uses the newest resolved article or heading date. Date orders are newest first, then slug. Article-title links provide the article summary and resolved Created and Updated dates as native hover text, with the dates on the final line. If a summary cannot be reduced to clean text, the hover text contains only the dates.
Wide landscape layouts place article and section navigation in a vertical left pane. Narrow portrait layouts use independent horizontal article, section, and conditional subsection rows. Short and narrow layouts hide descriptive build metadata while retaining the generator identity, Contact, and license controls.
DEFAULT_THEME selects the initial exact variant.
DEFAULT_THEME_MODE selects the initial mode:
off: omit the mode control; apply
DEFAULT_THEME unchanged.
exact: apply the selected theme unchanged.auto: select the mapped variant using the browser preference.light or dark: select the corresponding
mapped variant.
Every value except off renders all four choices. An
unmapped theme remains fixed in every mode.
DEFAULT_THEME_SELECTOR enables the selector from
tools/theme-menu.html. Single-page selections span all
articles until reload. Multi-page selections reset when another page
loads. The mode control is independent of the Theme selector.
Light and dark pairs are the data-auto-light and
data-auto-dark attributes in
tools/theme-menu.html. Edit those attributes to change a
pairing.
SITE_FEED=true writes feed.atom, feed discovery
metadata, and a text-form Atom link before the Theme control. Listed
articles opt in through data-feed-sections:
h2, titled "Article title - Section heading",
with a link to that section instead of the article summary.
h2, with a linked list of its h3 headings
in each entry body.
Feed rules:
h2 and h3 fall back to h1
without h2 headings. In h3 mode, an
h2 without child headings has the same content as
h2 mode.
h1 entry uses the newest article or heading date. An
h2 entry uses its data-modified, then its
data-created, then the article's resolved modification date.
h3 updates its parent entry when newer. An undated
h3 has no effect. Article-level auto rolls into
h1 entries; in section modes it is only the fallback for an
undated h2. Feed dates use midnight UTC.
SITE_MODE and SITE_URL_STYLE.
IDs remain SITE_URL/#article-id or
SITE_URL/#section-id, independent of dates and output
mode.
h2 headings
create entries; section edits and added h3 links retain the
parent entry ID.
SITE_ICON supplies the Unicode header logo and generated
favicon when SITE_ICON_PATH is empty.
SITE_ICON_PATH supplies an SVG copied unchanged as the
favicon and used as the header logo.
SITE_ICON_PATH_THEME=true embeds the header copy and maps its
colour-out and
colour-in classes to the current article background and title
colours. See Custom site icon under BUILD for class assignment.
SITE_BACKGROUND enables a fixed article-pane SVG backdrop.
SITE_BACKGROUND_RANDOM lets supporting browsers select its
scale and crop with CSS random() when loading the document.
Other browsers retain the SVG's base fit. The bundled SVG uses a centred
cover crop. Its colour-out class is not painted;
colour-in uses the panel background colour at 25% opacity.
Code, download, and image block surfaces remain opaque.
Contact opens a native popover:
contact-confirmation.
The first query item is a lowercase SITE_TITLE identifier
followed by _contact=1. Runs outside letters, digits, dots,
underscores, and hyphens become one underscore; edge underscores are
removed. Identifiers without ASCII letters or digits become
arachnopress. Defaults are
arachnopress_contact=1 for release and
arachnogoat_contact=1 for build and full.
HTTPS encrypts the request in transit. The address and message remain in the URL, browser history, and logs that record the query string. Do not submit confidential information. The static site provides no separate message delivery or storage.
The operator extracts and processes marked requests from the server log. arachnopress provides no log-processing component.
The license popover HTML-escapes and embeds
tools/license.txt. Its first non-blank line is the title.
THIRD_PARTY_NOTICES.txt maps bundled colour palettes to
notices below licenses/.
site/ with the
deployment files, every source article, and newly generated output.
Leaves release markers and archives unchanged.
site/. It creates the versioned archive in the project root,
removes all arachnopress_*.tar.gz source article archives,
and updates the source marker.
site/, removes
all arachnopress_*.tar.gz source article archives, and
updates the source marker.
No clean, install, serve, or watch target is defined.
RELEASE_SITE_ENV defines release site defaults.
PUBLIC_SITE_ENV defines build and full site defaults.
BUILD_ENV defines shared defaults. Environment and
command-line make values override them.
arachnopress for release and
direct tools/build.sh use; arachnogoat for
build and full.
true writes feed.atom, its discovery metadata,
and a header link. Listed articles opt in with
data-feed-sections. false omits them.
Defaults: false for release and direct
tools/build.sh use;
true for build and full.
SITE_FEED=true
requires an absolute HTTP or HTTPS URL without a query or fragment. A
trailing slash is removed. Defaults: empty for release and
direct tools/build.sh use;
https://arachnogoat.com for build and
full.
SITE_TITLE for
release and direct tools/build.sh use;
musol@arachnogoat.com for build and
full.
SITE_TITLE and rendered into the
generated SVG favicon. Defaults: U+4DD6 for release and
direct tools/build.sh use; U+4DEA for build
and full.
#rgb or #rrggbb.
When empty, the header icon follows the current article-title colour
and the generated favicon uses the SVG default text fill. It is unused
when SITE_ICON_PATH is set. Default: empty.
site/favicon.svg and uses it beside
SITE_TITLE. SITE_ICON and
SITE_ICON_COLOUR are then unused. The path must not name
the generated favicon.svg. Defaults: empty for
release;
articles/arachnopress/arachnogoatsundual.svg for
build and full. Direct
tools/build.sh execution defaults to empty. Restore the text
icon with SITE_ICON_PATH= and
SITE_ICON_PATH_THEME=false.
true embeds the SITE_ICON_PATH SVG in the
header and maps its colour-out and colour-in
classes to the current article background and title colours. The
favicon remains an unchanged copy. true requires
SITE_ICON_PATH. false uses the SVG as an external
header image. Defaults: false for release and
direct tools/build.sh use; true for
build and full.
true embeds the
SITE_BACKGROUND_PATH SVG. The bundled SVG uses a centred
cover crop; a replacement's root SVG attributes determine its base fit.
Defaults: false for release and direct
tools/build.sh execution; true for
build and full.
true lets browsers with CSS
random() support select a scale and crop on page load;
unsupported browsers retain the base fit. false always
uses the base fit. Default: true.
SITE_BACKGROUND=true, the file must define
colour-out and colour-in classes. The former is
not painted; the latter uses the active theme's panel background colour
at 25% opacity. Default:
articles/arachnopress/arachnogoatsundual.svg. Use
preserveAspectRatio="xMidYMid slice" for a centred cover
fit.
arachnopress.
GENERATOR_LABEL and used
in release archive names and Atom generator metadata. It contains
dot-separated digits. Default: 1.0.64.
tools/theme-menu.html, with or without
the theme- prefix. Defaults: solarized-dark for
release and direct tools/build.sh use;
everforest-hard-dark for build and
full.
off omits the control and applies
DEFAULT_THEME unchanged. exact,
auto, light, or dark render all
four choices and select that initial mode. Auto follows the browser
preference; Light and Dark use the selected theme's mapping. An
unmapped theme remains fixed. Defaults: off for
release and direct tools/build.sh use;
exact for build and full.
true renders the selector in either
output mode; false fixes the selection to
DEFAULT_THEME. Default: true.
single-page writes all generated articles
to index.html. multi-page writes
index.html plus one slug.html per article.
Default: single-page.
true enables unlisted output
using the selected SITE_MODE; false excludes
unlisted articles from generated HTML and navigation. Defaults:
false for release and direct
tools/build.sh use; true for build
and full.
html retains .html links.
extensionless keeps generated .html files but
uses slug and ./ for multi-page navigation, home
links, and contact actions. Defaults: html for
release and direct tools/build.sh use;
extensionless for build and full.
Extensionless output requires a matching web-server rewrite.
Single-page output is unchanged.
title, created, or
modified. Default: title.
pygments, source-highlight, or
none. Default: pygments.
23.
static-site-build.* rendering
directories. Default: /tmp. Target staging uses
.site-build.* below the project root.
LC_ALL is set to C.
SOURCE_HIGHLIGHT_DATADIR is unset so Source-highlight uses
its installed data files and the project output definition.
make build is the normal target. Run it from the project root
after changing articles, assets, styles, tool inputs, or build settings.
Store the SVG below an included article. For theme colouring, assign
colour-out and colour-in classes to its drawable
elements or groups. Edit the class attributes directly or with Inkscape's
XML Editor. Restore the Unicode icon with SITE_ICON_PATH=
and SITE_ICON_PATH_THEME=false.
Maintainers changing the generator update GENERATOR_VERSION
and run make release. This builds only the arachnopress
article and creates the root archive. Copy that archive into
articles/arachnopress/, then use make build for a
normal site. The optional make full target performs the
archive integration within its staged output.
HIGHLIGHTER=none selects escaped source. Select either
installed highlighter explicitly to test its output.
make build after changing maintained input.
Stylesheet and favicon cache tokens change with their resources.
.site-build.* below the project root and
static-site-build.* below TMPDIR before
removing leftovers.
No clean target is defined. Remove site/ without changing
maintained source. Release replaces the current-version root archive but
does not remove older root archives. Remove obsolete root archives by
exact name.
make in this directory.
SITE_ICON_PATH.
Its link contains a cache version token.
SITE_FEED=true.
DEFAULT_THEME_MODE is not off
and a reachable theme has an automatic mapping. It contains light/dark
rules derived from styles.css and the mappings in
tools/theme-menu.html. Its link contains the shared
stylesheet cache token.
site/ and release archives.
site/ and release archives.
site/articles/<slug>/.
make release and
consumed by make full from the same project root. Its
top-level directory has the same name without the .tar.gz
suffix.
A target exits zero after its complete staged tree is published as
site/, after release packaging when applicable, and after
managed source cleanup. It exits non-zero on invalid settings or article
structure, missing required tool inputs, duplicate or invalid IDs, no
articles, or an unhandled command or filesystem failure.
Optional highlighting and checksum failures are not fatal. The build either emits escaped raw source or omits the checksum.
make release with the same generator version before
make full. Run both commands from the same project root, not
from site/.
tools/theme-menu.html. Define
data-auto-dark and data-auto-light together,
and include the source theme in its pair.
data-listed="false".
.svg file in the staged tree. A
themed icon must contain colour-out and
colour-in class tokens.
.svg file in
the staged tree containing colour-out and
colour-in class tokens.
Missing or invalid generated block files appear as visible missing blocks. They do not produce these fatal diagnostics.
Deploy site/ as static files without changing its relative
paths. It may instead be opened as site/index.html through
file://; multi-page file access requires
SITE_URL_STYLE=html.
Contact submission is for HTTP or HTTPS deployment. Serve contact forms over HTTPS and retain query strings in the access log to receive their contents.
The OpenBSD httpd(8) example serves .atom as
application/atom+xml and rewrites extensionless article
paths. Replace its host and document-root paths, validate the
configuration, and reload httpd.
Its final rule appends .html internally to a missing final
path component without a dot. Keep specific rules before it.
Article HTML, a SITE_ICON_PATH SVG embedded by
SITE_ICON_PATH_THEME, and a
SITE_BACKGROUND_PATH SVG are trusted author content. The
build escapes generated text and code, but does not sanitize author HTML
or embedded SVG markup. Review them before building. The zero-JS
guarantee applies to the generated interface; author HTML may add its own
active content or external dependencies.
Single-page output contains every generated article and highlighted code
span. Large code-heavy collections increase HTML size and DOM cost. Use
multi-page mode, focused excerpts, raw downloads, or
HIGHLIGHTER=none when that cost becomes material.
Older clients may not support every CSS or popover feature. See REQUIREMENTS.
arachnopress is distributed under the BSD 3-Clause license. See
tools/license.txt or the License control in the site metadata.
Bundled colour palettes retain their upstream values and third-party
licences; see
THIRD_PARTY_NOTICES.txt and licenses/.