Web delivery standard
A public page is the firm's shop window and, more and more, its sales channel: it is what a search engine ranks, what a messenger turns into a preview card, what a customer on a phone in a workshop waits for. The platform delivers it the way the professional content and commerce systems do — the document lean and saying what it is first, everything heavy an external versioned file a cache may keep, pictures sized and lazy, nothing third-party before the visitor asks for it — and it measures that on every deploy so the standard cannot quietly erode.
Nothing here is configured. It is how the web channel behaves for every firm, with the one accent colour a firm already sets.
The document
The page's own words come first. <title>, the description and the share
card (Open Graph, Twitter) sit inside the first 8 KB of the document,
ahead of every stylesheet and script.
Why the first 8 KB
A preview is not always built by a server with a megabyte to spare. A phone composing a link preview inside an encrypted chat reads the start of the page and stops. On 2026-09-14 the ctrl32.com front page carried its share card past byte 209 000, behind 200 KB of inlined styling — a messenger showed the bare address and nothing else. The metadata now begins around byte 7 000.
The site's styling is an external, versioned, immutable file: the global sheet is hashed by the build and may live in every cache for a year; only a component's own few kilobytes of style stay inline, and no inline style block may exceed 8 KB. The Appearance cascade a firm edits reaches the web once, through its versioned stylesheet — the same cascade used to be inlined, serialised again into the page's hydration data, and linked.
The front page of a configured site stays under 100 KB uncompressed, and its hydration data (the page's own state, embedded for the browser) under 60 KB.
The interface catalogue is a file, not page data
The words the web shell itself says — search, pagers, the cart, the toolbar, the language menu — are translated from the same register as every other channel. Two things keep that light:
- the web asks only for its own words. The product's translatable
strings are recorded with the channel whose code asks for them (a
shipped manifest,
modules/translation/channels.json, written byinterface_translations --sync); the back office's and the ERP's strings never travel to a website. A string the manifest does not know passes through — the filter removes only what is provably somebody else's. - the catalogue is an external, versioned, immutable address
(
/api/v1/translations?lang=sk&v=<stamp>), the way the reference commerce platform ships its per-locale translation file: the server renders the page with it and then leaves it out of the page's data; the browser fetches the same address before it takes over the page — once, then from its cache for a year. Every edit of a translation is a new stamp.
Why
Before this the Slovak front page of ctrl32.com weighed 381 KB against 97 KB in English: 316 KB of translations — 4 511 strings of the whole product — rode every non-English page, thirteen languages times every site.
Media a browser may keep
| What | Cache answer | Why |
|---|---|---|
a public file (/storage/f/…/, and its styled derivatives) |
public, max-age=86400 + ETag + Last-Modified; a repeat request with the validator answers 304 with no body |
anybody's file, so a shared cache may keep it a day; a day bounds the staleness of a picture replaced under the same address |
| a private file, or a file opened through a share link | private, no-store |
one person's answer — nobody stores it |
| the site stylesheet with its version stamp | public, max-age=31536000, immutable |
every Appearance edit changes the stamp, so the old address is never wrong |
| the site stylesheet without a stamp | no-cache (revalidated) |
an old page's link must not stick |
the shell's static assets with ?v=<build> |
a year, immutable | a new build is a new address |
A 304 is not a read: the read trail of customer-owned files counts people, not caches.
The edge cache is the operator's step
Cloudflare caches by file extension by default, and a stored file's address
has none (/storage/f/<uuid>/). The answers above make an edge cache
correct; to make it happen, add a Cache Rule for /storage/f/*
("eligible for cache", respect origin headers) in the zone. Without it every
visitor's browser still keeps the file; only the edge does not.
Pictures in text
An editor drops a picture into a body, a block or a product description and the reader gets it the way image styles deliver a listing picture:
- its intrinsic size (
width,height) — the layout reserves the box before the bytes land, so nothing jumps; - lazy past the first — the first picture of a text is the likely hero
and loads at once; every following one waits for the scroll and decodes
off the main thread. An author who writes
loading="eager"orlazyon a picture is obeyed over that rule; - a responsive WebP source set from three shipped image styles —
responsive_480,responsive_960,responsive_1440— for every rung narrower than the picture, plus one at the picture's real width (never upscaled), with the original as the fallback source; - the authored alternative text, verbatim — never invented, dropped or altered. A picture without one is reported by the audit.
Animated pictures and vector marks get size and loading but no derivative (a derivative would drop the frames or the scalability). A picture that cannot be turned into a derivative is delivered as the original — once remembered, the failure is not retried on every view.
The three rungs are ordinary image styles (Structure → Image styles): an administrator who edits one changes every body picture with it; deleting one drops that rung.
A picture that entered the store before the platform measured sizes (or through a door that skipped it) is measured from its own bytes the first time a page delivers it, and the size is remembered — at most eight such pictures per page view, so one page never pays for a whole backlog.
A heavy placed map fetches its shapes
A map block with many or large shapes — a delivery firm's coverage zones, thousands of places from a view — carries no geometry in the page. The page names the block's own door, stamped by the block's last edit; the map asks it once the page stands and the browser keeps the answer for a year (a view-fed map, whose places change with content, five minutes). Up to 500 features or 8 KB of JSON stay inline. The same rule has applied to map views since the geo work of 245.
Why
coldexpress.sk's coverage map — ten zones, 5 198 coordinates, 106 KB — rode every page of the site twice: as the map's data and inside the block's rendered markup.
Embeds that wait for the reader
A hosted video (YouTube) renders as a still frame — the authored poster when the document has one, else a dark frame with the title and a play control. Nothing is fetched from the video host and no third-party cookie is set until the reader presses play (pointer, Enter or Space); then the player appears and starts, on the privacy-preserving host. A chapter link on the frame starts the player at that chapter. Without scripting the page shows the title, a link to the video and the outline — the content was there all along.
Why not a thumbnail from the video host
A thumbnail fetched from the host is a third-party request before anybody
asked for the video, and the platform never fetches from outside at render
time. Give the video a poster: in the document and the frame shows it.
Nothing the visitor does not need
An anonymous visitor's page load asks for nothing only a signed-in person has: no toolbar identity check (it answered unauthorised on every page), no cart for a visitor with no session, no flag images for a language menu that is closed. The server sees whether the request carried a session and tells the page; a signed-in person and a visitor with a basket still get the toolbar and the cart exactly as before.
Colour and names, accessible by derivation
A firm sets one accent. Text and controls drawn in it use the nearest shade of the same hue that meets the AA minimum (4.5:1) — one shade for the light page, one for the dark page — derived by the platform. Surfaces (the hero band, the brand mark) keep the accent exactly.
Why derive instead of asking
ctrl32's accent #2e99f5 is 3.0:1 on white. Used verbatim for links and
buttons it produced 29 contrast failures on one page — and would have on
every firm's page whose accent is light. An accent that already passes is
used unchanged.
Controls whose spoken name differs from what they show (the language switcher shows "English") are named so the spoken name contains the visible text.
The front page's description
A front page with no authored description (Meta tags → site defaults) says the firm's tagline (Appearance → Branding) as its description and share text, so a search result or a preview card never shows the bare address. Nothing is invented: no tagline, no description; an authored description always wins; a record page keeps its own words.
The audit
manage.py web_audit --url https://ctrl32.com [--page /download/ …] [--lighthouse report.json] [--json]
Fetches the front page (and any --page) anonymously and measures every
budget; exit code 0 when all hold, 1 naming each breached budget, 2
when a page could not be fetched. The deploy runs it for every site after
the containers are up and writes the report into the deploy log.
| Budget | Holds when |
|---|---|
document_bytes |
the front page is ≤ 100 000 B uncompressed |
payload_bytes |
the front page's hydration data is ≤ 60 000 B |
meta_offset |
title, description and og:image are all within the first 8 192 B |
largest_style |
no inline <style> body exceeds 8 192 B |
appearance_dup |
the linked Appearance sheet does not also appear inline or in the hydration data |
pictures_size |
every platform picture declares width and height |
pictures_alt |
every picture carries an alt attribute |
file_cache |
sampled public files answer public, max-age ≥ 86400, ETag, Last-Modified, and 304 on repeat |
sheet_cache |
the versioned site sheet is immutable |
requests, transfer_bytes, third_party, status_4xx |
from a Lighthouse report: ≤ 30 requests, ≤ 600 000 B, no third-party request, no 4xx before interaction |
The browser-side budgets need a browser: run Lighthouse on a workstation and
hand the JSON to --lighthouse.
Measured on the reference page
ctrl32.com front page, Lighthouse 13, simulated mobile.
| Measure | Before (2026-09-14) | After (2026-09-14, deploy of 4f5e939a) |
|---|---|---|
| Lighthouse performance / accessibility | 79 / 93 | 96 · 89 · 90 (three runs, median 90) / 93 — the last 24 contrast items are the firm's own Appearance CSS (see below) |
| Largest contentful paint | 4.2 s | 2.3 · 2.9 · 2.8 s |
| Requests / transferred, before interaction | 53 / 1.58 MB | 26 / 285 KB |
| Third-party bytes before interaction | ≈ 1.0 MB | 0 |
| HTML document, uncompressed | 351 KB | 97 KB |
| Byte offset of the share card | 209 163 | 7 418 |
| Largest inline style block | 143 KB | 6.5 KB |
| Public image cache lifetime | none | a day + validators, 304 on repeat |
| 4xx on an anonymous load | 1 | 0 |
| Colour-contrast failures | 29 | 24, all in the firm's own CSS (#2E99F5 text on white in the hero and pricing sheets); 0 once those sheets use var(--accent-text) |
web_audit --url https://ctrl32.com |
— | result: PASS |
Slovak front page (/sk/), document / hydration data |
381 KB / 325 KB | 99 KB / 44 KB (the catalogue is a cached file: 55 KB, 589 strings instead of 4 511) |
| coldexpress.sk front page, document / pictures without a size | 697 KB / 17 | 72 KB / 3 (the coverage map's 106 KB of zones now come from the block's own door, cached for a year; three pictures the store cannot measure keep their tags) |
What is still the firm's to do
- Appearance → Custom CSS of ctrl32: the hero and pricing-cards sheets
colour text with the raw accent (
#2E99F5, 3:1 on white). The repository copies (tools/sites/ctrl32/hero.css,pricing-cards.css) already usevar(--accent-text, #0a75d2)for text; paste them over the live sheets. - Cloudflare Cache Rule for
/storage/f/*(see above). - A
poster:for the front-page video, so the facade shows a still instead of the dark frame.
The deploy's own audit
After the deploy update.sh runs the audit for every site. On 2026-09-14
ctrl32.com passed; coldexpress.sk failed document_bytes (697 KB — the
language catalogue rides the hydration data of every non-English page,
the next feature), meta_offset and pictures_size (its block pictures
are not rich text); fabrikaerp.com timed out from inside the container
(the origin cannot reach its own public hostname — run the audit from a
workstation for that site).