Substrate

Template documentation

Substrate template guide

Everything you need to customise and ship this template. Roughly a ten minute read.

File structure

substrate/
├── index.html          Overview page, contains the 3D hero
├── product.html
├── pricing.html
├── about.html
├── contact.html
├── 404.html
├── docs/index.html     This guide
└── assets/
    ├── css/main.css    All styles, token-driven
    ├── js/main.js      Nav, form, preview dock
    ├── js/scene.js     The three WebGL heroes
    ├── vendor/         Three.js r185 (MIT)
    └── img/

Getting started

There is no build step and no dependencies to install. Open index.html in a browser, or upload the folder to any host.

One caveat: the scripts are ES modules, so opening the file directly with file:// will be blocked by the browser. Run a local server instead — npx serve or python3 -m http.server both work.

Changing colours and fonts

Every colour is a custom property at the top of main.css. Change --accent and the buttons, links, focus rings and 3D hero all follow. The four bundled accents are defined just below as [data-accent="..."] blocks — add your own the same way.

Fonts are loaded from Google Fonts in each page head. Swap the link and the two font-family declarations in main.css. Both bundled families are open-licensed.

The 3D hero

Set the default in main.js, in the prefs fallback object: variant: "lattice" | "orb" | "flow".

The hero is procedural — there are no model files or textures, so nothing to optimise or licence. To change its size or shape, edit the constants at the top of each builder function in scene.js. Colours are read from your CSS variables, so retheming the site rethemes the hero.

The scene stops rendering when it scrolls out of view or the tab is hidden, and renders a single static frame for visitors who have reduced motion turned on.

Removing the preview dock

The floating Preview options panel exists so buyers can try the variants. Before you launch, delete two things: the <div class="dock"> element near the bottom of each HTML file, and the initDock(); line in main.js. Nothing else references it.

Connecting the form

The demo form validates in the browser and stops there. In main.js, find initForm() and replace the success branch with your own fetch() to Formspree, Basin, Netlify Forms or your API. Keep the role="status" element — it is what screen readers announce.

Performance notes

Device pixel ratio is capped at 2. On the 1024px breakpoint and below the hero drops to a shorter stage. If you are targeting low-end mobile, lower COUNT in the flow variant or the grid size in the lattice variant.

Credits and licences

Three.js r185, MIT — included in assets/vendor/ with its licence file. Bricolage Grotesque and Public Sans, SIL Open Font Licence. All 3D geometry, copy and layout are original to this template. No stock photography is bundled, so there is nothing to relicense.