Skip to content

Spec Theme

Spec is a dark, immersive storefront theme where the product is the hero. It suits premium tech, audio and other considered purchases, where a shop sells a handful of things it wants shown properly rather than a wall of thumbnails. It is built on top of Nova (Spec → Nova → Bootstrap template fallback), so every page works from the moment a site switches to it; Spec replaces the pages where the product should lead.

Site admins pick it under Admin → Shop Settings → Theme (Choosing a Theme); platform staff can also set it per site in System → Tenants → {site} → Theme (theme name Spec). A site's Design Brief (brand colour, font, corner radius, image shape) applies to Spec as it does to Nova; the brand colour replaces Spec's default brass accent.

Design principles

Principle What it means on the page
The product leads A small range is shown as large alternating rows, not a dense grid. Product images sit on a lit stage against a deep ink-teal canvas.
One accent The accent (--color-primary, brass by default) marks the action: Add to basket, View, the search button, the current filter. On a product page it follows the selected colour.
Values are monospaced Prices, SKUs, stock lines and labels use IBM Plex Mono; headings use Unbounded; reading text uses Instrument Sans.
Minimal chrome A translucent header with hairline rules, no boxes around things, big dark space.
Nothing is invented Spec only shows what the catalogue holds. See Left out on purpose below.

What Spec redesigns

Area Highlights
Header / footer Optional announcement and promise strips, a translucent sticky header with the search field, account and basket, a category row with mega menu (collection menu and admin-built menu), slide-in mobile menu, reassurance row, payment marks.
Collection page Showcase mode for a curated range (8 products or fewer, all on one page): a large heading, then one alternating row per product with the image on a spotlight, index, brand, name, short description, price and a View button. Grid mode for anything bigger or paginated: the category tree beside a grid of large dark cards with sort and pagination, so a 200-product collection stays usable.
Search and merchandising Toolbar with count and sort, applied-filter tags, persistent filter rail (a bottom sheet on phones), the same large-card grid, pagination.
Product page A tall stage on the left (the gallery) that stays in view while the story scrolls on the right: heading and summary, a buy panel (options, price, stock, quantity, Add to basket), the specification table, then description and delivery information. Below 900px the columns stack; with reduced motion requested nothing sticks. A docked buy bar appears on phones.
Colourway When a product has a colour option (an option group whose code or label contains colour, color, finish or shade), the page accent is recoloured from the selected value using a small palette. Unknown colour names and products without a colour option keep the default accent.
"Added to basket" A compact panel under the header showing the item and the new subtotal (a bottom sheet on phones).
Rails Trending, featured and recently-viewed products use the card.
Specification table The product attributes extension is restyled as a hairline spec table (monospaced labels and values).

Basket, checkout, order confirmation, account pages and the blog render Nova's templates inside Spec's header and footer. Nova's grey ramp is inverted and its surface, text, border and primary tokens re-pointed, and Bootstrap 5's colour variables are set to dark values, so those pages are legible on the dark canvas; Stripe's payment fields sit on a light panel because Stripe draws them on a light theme. They are not redesigned in Spec.

Products without images

A product with no image gets a designed empty state (a ring with the product's initial on the stage) on cards, showcase rows and the product page, instead of the generic placeholder.

Left out on purpose

The design concept included a few things the catalogue has no data for. Spec leaves them out rather than inventing content; each returns when the data exists.

Concept Why it is not there
Model comparison table Products carry free-form attributes, not a structured specification that can be compared across a range.
Spec chips on showcase rows (driver size, battery hours) Same reason. The product page shows attributes as a table when the product attributes extension is placed.
Annotated call-outs, battery gauge, sound rings Illustrated renders, not catalogue data.
Finance line ("From £32/month") No finance data or provider.
In-the-box list Not part of the product model.
Per-row colourways on the collection page Colour is a variant option; only the product page reads it. Showcase rows use the default accent.
Review score breakdown and quotes Only an average rating exists; it shows as stars when present.

Configuring the copy

The "Shop all {0}" link at the foot of each admin-built menu dropdown (spec.nav.shopAll) can also be reworded or hidden per site with the nav-mega-menu-view-all-label and nav-mega-menu-view-all-enabled site config keys; see Brock: the "Shop all" link.

All Spec wording is in messages.properties under spec.* and can be overridden per site in Admin → Shop Settings → Site Text (/admin/shopSettings/text). The ones a merchant should set:

Key Default Where it shows
spec.promise.delivery (empty) Promise strip, product page, footer. e.g. "Free next-day delivery"
spec.promise.returns (empty) As above. e.g. "30-day returns"
spec.promise.secure Secure checkout Promise strip, product page, footer
spec.promise.help (empty) Footer reassurance row
spec.pdp.deliveryInfo (empty) "Delivery & returns" section on every product page (HTML allowed)
spec.pdp.priceNote (empty) Line under the product price, e.g. "Prices include VAT"
spec.pdp.specTitle Specification Heading of the attributes table when the extension has no title
nav.banner.message (empty) Announcement bar above everything

The promise strip only appears once delivery, returns or an announcement is set.

For developers

  • Templates: web-mvc/src/main/resources/templates/spec/. Styles and behaviour: resources/settBuilder/themes/spec/css/spec.css and js/spec.js, linked from Spec's fragment/head.html after Nova's bdgr.css (and before the Design Brief's theme.css).
  • Spec's ThemeContext points cssPath/jsPath/imagePath at Nova's folders so Nova templates and extension scripts keep working; see Theme Resolution.
  • Icons are in fragment/spec-icons.html (not icons.html) so Nova's payment-mark icons keep resolving. The fragments Spec shadows (head, nav, footer, mini-basket, account-status, facet-rail, sort-dropdown, pagination, auth-head) keep Nova's fragment names and signatures because Nova's pages call them too.
  • Showcase or grid is decided in CollectionController and arrives in the template as showcaseLayout: true when the collection has products, all of them are on this page, and there are no more than the site's Showcase Layout Limit (collection-showcase-max, default 8, set 0 for grid always). Search and merchandising pages never use showcase. Themes without a showcase layout ignore the value.
  • Colourway lives in spec.js: it watches Nova's variant picker (#variantSelector), finds a colour-like option group and re-points --sp-accent (and --sp-on-accent, the text on it, chosen for contrast) on <html>. The palette is one small table at the top of that section.
  • The stage: product images sit on --sp-stage (a light spotlight) with mix-blend-mode --sp-img-blend, so photos with white backgrounds melt into it and transparent cut-outs sit on it. For a fully dark stage set --sp-stage-a/-b to dark values and --sp-img-blend: normal.
  • Nova pages Spec does not override are made legible by token re-points at the top of spec.css, plus a block that neutralises hard-coded white backgrounds in Nova's inline <style> blocks and gives Stripe's containers a light surface. When Nova adds a new inline-styled component, check it on a Spec site.
  • Fonts (Unbounded and Instrument Sans variable fonts, IBM Plex Mono) are self-hosted from @fontsource packages: the Latin and Latin-ext subsets are vendored (see scripts/copy-versioned-deps.js) and declared inline in fragment/head.html. No request goes to a third-party font host.
  • The theme record is added by system update 90.json (idempotent) and initialisation/templates.json.