Project Notes

arachnopress

zero-JS, cookie-free, monolithic static site generator

DESCRIPTION

arachnopress builds a zero-JS, cookie-free static site from simple hand-written HTML fragments within subdirectories of articles/. It has no Markdown layer or client-side runtime, and provides freedom to include any HTML content the user requires.

The build writes a single index.html with dynamic theming, flexible navigation and layout suitable for desktop or mobile, sortable article and section indexes, a static contact form, image and download blocks, and collapsible code blocks with plain-text or optional server-side syntax highlighting (escaped/tokenized at build time).

All dynamic features are provided using only the CSS within styles.css (provided as-is) and nav-sections.css (created at build time).

The build is broadly POSIX-compatible, using sh, make, and standard Unix tools, supporting BSD, GNU/Linux, macOS, and others. The only known POSIX exceptions are: mktemp (broadly available) and the optional syntax highlighters, pygments or source-highlight.

FILES

Source articles are read from articles/. Generated index.html and nav-sections.css are written at the project root.



    


    


    


    


    


    


    

  

BUILD

Run the build from the project root. Settings may be supplied through the environment or make command line. Make passes them through the recipe environment; defaults remain in tools/build.sh.


  

SETTINGS

The build accepts site identity, separate generator name and numeric dotted version, default theme, article order, highlighter, automatic code footer threshold, license file, and copyright holder.


  

ARTICLES

Article format

Each article is stored at articles/<slug>/article.html. Its article id must equal the directory slug and data-title is required. Optional data-created and data-modified dates control sorting. Missing creation dates use the current UTC build date; missing modification dates use the creation date. Interface, article, section, and generated block IDs share one collision registry. The build emits title, creation, and modification order lists.



    

Build process

Generator markers are file-backed, one-line empty elements. Referenced paths may contain subdirectories but must be relative to the article and must not escape it. Displayed sizes and checksums use the raw files.



    

  

SECTION INDEX

Section headers and scan

Plain one-line h2 and h3 headings are included in the article's section index. Each h3 belongs to the preceding h2. The build preserves an explicit id or generates a safe unique anchor.



    


    

Section index layout and css

Shared index layout is defined in styles.css; nav-sections.css selects the current article and section. Landscape subsections flow within the single vertically scrolling section list. Narrow portrait navigation lists are independent horizontal scrollers with fixed tracks for scrollbar stability, while their metadata remains in a compact non-scrolling row. Landscape labels step down in size from article to section to subsection. A selected subsection uses a quieter palette variation while its parent section retains the primary highlight.


  

CODE BLOCKS

Markers

A code marker is an empty one-line pre with an article-local data-src. data-lang selects highlighting; data-title, data-note, and data-open control displayed metadata and initial state. data-header="false" emits an always-visible standalone block without a summary or controls. A normal block's raw link targets the source file. Its footer repeats the title, size, raw link, and top link.



    

Display variants

A headerless block has no footer by default. Explicit data-footer="true" adds a footer with the title, size, and raw link; no navigation arrow is rendered because there is no header target.



    


    

Safe rendering

Raw code is escaped before insertion. Highlighted output is used only when the selected highlighter succeeds. Otherwise escaped source is emitted.



    


    

Footer behaviour

Without data-footer, blocks at or below CODE_FOOTER_LINES omit the footer. Explicit true or false overrides the threshold. Headerless blocks ignore the threshold and require an explicit true.

IMAGES

Markers

An image marker is an empty one-line figure with an article-local data-src. It accepts data-alt, data-caption, data-open, data-title, data-note, and data-footer. data-header="false" emits an always-visible standalone image without a summary or controls. Its footer is absent by default; explicit data-footer="true" adds the title, size, and raw link. Images are lazy-loaded and contained within the themed block. A normal block's footer also contains a top link.



    

Rendering


  

DOWNLOADS

Markers

A download marker is an empty one-line div with one article-local data-src. Optional data-title and data-note change displayed text, not the target. The rendered link shows the raw file size and a SHA256 checksum when a supported local checksum tool is available.



    

Rendering


  

SYNTAX HIGHLIGHTING

Pygments is the default highlighter; Source-highlight and no highlighting are also supported. With Pygments, an omitted language uses filename inference and data-lang="auto" may also guess from content. An explicit language requests that lexer. Missing tools and failed highlighting fall back to escaped source. Successful highlighted output is filtered to unwrap whitespace-only Pygments and Source-highlight spans, preserving their whitespace while reducing the generated DOM.



    

Source-highlight uses tools/html-fragment.outlang to emit an HTML fragment rather than a complete document.

THEMES

Theme selection uses HTML radio inputs and CSS only. The build copies tools/theme-menu.html, marks the configured default, and uses :has() to select theme variables. The checked theme is highlighted using the active theme palette.


  

LAYOUT

Responsive layout

The page has a sticky header, an article index, and an article pane. The first article is shown by default; URL fragments select other articles and sections.



    

Wide layouts use a side index with subsections nested below the selected section. Narrow portrait layouts use horizontal article and section rows, adding a third subsection row only when the selected section has one. All layouts use document scrolling. Article content has a bounded readable width, while section headings retain a wider manual-page span. Fixed portrait navigation tracks reserve scrollbar space, while the metadata row is sized to fit without one. At portrait widths of 360px or less, and landscape heights of 330px or less, the descriptive and build-date entries are hidden while the generator identity, Contact control, and license remain. Coarse-pointer controls retain touch-sized targets. Landscape side indexes reserve room for two complete items in each main list, then give the article and section lists approximately one third and two thirds of the remaining space. A short article list stays content-sized so its unused share passes to the section list.

Article selection


  

STYLING

Block styling

Code, images, downloads, popovers, indexes, and highlighting classes use shared theme variables in styles.css. Syntax colours retain each palette hue while mixing toward a readable foreground; Pygments token subclasses keep distinct semantic roles.



    

Syntax colours


  

CONTACT

The metadata Contact control opens a native HTML popover containing an optional reply address and a required message of at most 500 characters. The zero-JS form adds a fixed <sanitised-generator-name>_contact=1 query item before submitting a GET request to the static site root. For the default name, this is arachnopress_contact=1, making contact requests easy to identify without coupling the marker to the generator version. Its fragment targets a CSS confirmation panel after the new page request. HTTPS encrypts the request in transit, but the values remain in the URL and server log, so the form warns against confidential information.

LICENSE

The license popover is rendered from a plain text template. The build replaces <YEAR> and <COPYRIGHT_HOLDER>; the latter defaults to username@hostname.


  

OUTPUT

The build completes temporary index.html and nav-sections.css files before publishing either output. The page links styles.css and embeds the favicon as a data URL.


  

SERVING

The generated files are static and can be served without any server-side scripting, or opened locally with file://. Minimal OpenBSD acme-client(1) and httpd(8) examples follow.

Acme client



    

Httpd