Skip to content

feat: replace the theme and the sample with a titanium fastener catalogue - #4

Merged
JasonYv merged 5 commits into
mainfrom
feature/titanium-fastener-theme
Oct 6, 2026
Merged

JasonYv merged 5 commits into
mainfrom
feature/titanium-fastener-theme

Conversation

@JasonYv

@JasonYv JasonYv commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

What this is

Phase 1A left the commerce theme with one product, one application note and one collection: enough to prove the contracts with Mallok, not enough to show what a shop on Nundar looks like. This replaces the theme and the whole sample with a complete site — a titanium fastener supplier's catalogue — ported from a React design supplied by the owner.

The shop plugin is not touched.

The five commits

Commit What it does
feat: replace the theme and the sample… The theme (13 layouts, 6 partials, one hand-written stylesheet, self-hosted fonts, four language packs) and the sample (31 bundles in English, German, French and Spanish; nine seeded variants), with their tests
docs: describe the titanium fastener theme… README, contributor and security notes, the design's new §15, and a record of the port
feat: filter the specification finder in the browser The theme's first script: filters and a search box above a table that is complete without it
feat: add the fastener calculators… The second: three calculators above a reference page that prints the same formulas, constants and tables
feat: add a preview command… npm run preview: a filled local shop on a throwaway database, in one command

Each of the two scripts is its own commit so that it can be left out; the pages are whole without them.

What changed in the model

  • A product is one page with its sizes on it, not a page per size. facets are the columns of the specification finder; sizes maps each SKU to what distinguishes it.
  • Three kinds are new: case, faq, tool. application is unchanged and the sample serves it at /industries.
  • The site's own words are theme options with a value per language in site.json. The theme's language packs hold only its own vocabulary.
  • Fonts are served by the site, under the SIL Open Font License, with each file's source and checksum beside it. The theme loads nothing from another host.

How to look at it

npm ci
npm run preview

About a minute later it prints the shop's address, the admin's, and a login. Nothing is kept: stopping it removes the database.

How it was verified

Check Result
npm run lint, npm run typecheck, npm run build Pass
npm run test:project 47 of 47
npm run test:shop 434 of 434 inside workerd; 175 of them the theme's
npm run smoke, npm run smoke:shop, npm run preview -- --check Pass on a real local Worker: 124 items published with their images, 56 header and footer links followed in four languages, all 17 of the theme's files fetched
Every page at thirteen widths, 320 to 1920 px 156 pages: none scrolls sideways, and no specification table does
Red and green More than 200 deliberate breakages — of templates, content, settings, the scripts and the set-up — each noticed by the check meant for it
Independent review of the theme Twenty-three defects confirmed, all fixed, each with a test

The calculators' script is held, by a test, to every constant and every table cell the reference page prints.

Not verified

  • No automated browser test exists. What the two scripts do to a page, the folded menu and the card layout were checked in a browser by hand, in one engine.
  • Nothing was tried with a screen reader.
  • The German, French and Spanish content was machine-checked for structure, links, references and digit-for-digit numbers, and not read by a native speaker.
  • Nothing was deployed, and no page weight or Core Web Vitals were measured.

For the owner to decide

  • The sample's facts. They come from the design and disagree with each other in places (the density of stainless steel, the weight saved, an iron limit, a grade named two ways, a passivation standard cited for the wrong metal). None was changed; the plan lists them.
  • The images. They were generated for the design. Whether they are to be published under this repository's licences is the owner's call.

What still waits for Mallok

Prices and availability on the pages and in the finder, and the cart page that the design's quote list becomes. Five smaller behaviours found during the port are written up for the Mallok side; each is handled here inside Mallok's documented contracts, and the design's §15 lists them.

…ogue

The theme proved the contracts with one product and three pages. It is now a
complete site, ported from the React design the owner supplied: a home page
with a specification finder, product pages built around a size table,
collections, industry pages, case studies, questions, an engineering
reference and plain pages, in English, German, French and Spanish.

- A product is one page with its sizes on it. `facets` are the columns of
  the finder and `sizes` its SKUs. Three kinds are new: `case`, `faq`, `tool`.
- Every sentence that belongs to the site is a theme option with a value per
  language in site.json. The theme's language packs hold only its own words.
- Fonts are served by the site, with their licences and sources beside them.
- No client JavaScript: the finder is the whole table, and the calculators
  are a page of formulas, constants and tables.
- 31 bundles in four languages replace the ball valve sample, with one seeded
  variant for each SKU a product page lists.

The tests render every layout twice, once with everything set and once for a
site that has filled in almost nothing, and hold the sample together: links,
references, attributes, SKUs and settings, in every language. The smoke run
publishes the real sample and follows every header and footer link.
The README's examples were still a ball valve, its setup steps asked for a
token that cannot upload the sample's images, and nothing said that the
contact pages need the inquiry plugin switched on before the first publish.

The design gains a section on what the theme changed in it: a product is one
page with its sizes, three new kinds, the site's copy as options per
language, and bundled fonts in place of system ones. The plan records how
the port was verified, what an independent review found in it, and what is
left for the owner, for Mallok and for tooling.
The template this theme was ported from let a buyer narrow the finder by
head type, thread, material and length. The port left the finder as the
whole table, which is right without a script and slow to read with one.

finder.js adds a list for each attribute, one for the sizes and a search
box above the table on the home page and in the catalogue, and hides the
rows that do not match. It is the theme's first script, on terms that hold
for any later one:

- The page is whole without it. The form is rendered by the server, hidden,
  in the page's language; the script fills it and shows it.
- It is declared in theme.json with its exact size and loaded only by the
  two layouts that have the table, and only when the table is there.
- It makes no request and stores nothing.

The logic is tested under node:vm, the markup inside workerd, and the
declaration against the templates and the file. What the script does to a
page was checked in a browser by hand.
The template's three calculators were ported as a page of formulas,
constants and tables: complete, and not something a reader can put their
own numbers into. calculators.js is the second of the two scripts the owner
approved, on the terms the first set.

A tool page asks for the calculators with `calculators: fasteners` in its
front matter, and the sample's reference page does in all four languages.
The forms are rendered by the server, hidden, with their labels from the
language pack and their numbers in value attributes; the script computes,
formats in the page's language and shows them. It is loaded by no other
page, makes no request and stores nothing.

The page under the forms is what makes the script checkable. A test reads
that page and compares it with the script: every constant, the limits of
every field, and every cell of every table.

The fields are found by a query and not through form.elements: a field
named "length" is not what that list returns under the name, which is why
the first run in a browser computed nothing. Three tests now hold the names
in the forms and in the script together.
Seeing what Nundar is took a dozen steps: local secrets, an administrator,
two plugins, an API token with three scopes, a publish and a seed, in that
order and before opening the site, because a page opened early stays in the
local cache for an hour. Each step is right for a site that will be kept,
and together they are a long way round for someone who wants a look.

`npm run preview` does all of it against a throwaway database and stays up:
the sample catalogue in four languages, the admin, and a login printed in
the terminal. Stopping it removes the database.

The set-up it needs is the one the end-to-end smoke run already had, so that
moved into scripts/lib/local-shop.mjs and both use it: what the preview
shows is what the smoke run checks. `preview -- --check` brings the shop up,
confirms the pages carry the site's own settings and that the printed login
works, and takes it down; CI runs it.

The README leads with the command and keeps the manual steps for a site
that keeps its data, with the two things that go wrong there said plainly:
a missing setup key, and pages cached from before the site was filled.
@JasonYv
JasonYv merged commit d0632ac into main Oct 6, 2026
1 check passed
@JasonYv
JasonYv deleted the feature/titanium-fastener-theme branch October 6, 2026 04:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant