Documentation

Lumen, end to end

How to upload the theme, what every theme setting does, what is on each page template, which module to reach for, and how the scroll motion works. Start at the top or jump to a section.

Photographer working in a daylit studio
Contents

Jump to a section

Each section below is self-contained. Field paths are written the way they appear in the theme settings panel, so you can search this page for the one you need.

01

Getting started

Upload the theme, set the four groups that decide how everything looks, then build the first page.

What Lumen is

Lumen is a HubSpot CMS theme for photographers and creative studios. It is built around large photography, oversized editorial headings and scroll motion: sections that hold on screen and are covered by the next one, a spiral image carousel, and headings that light up word by word as you read them.

The palette is monochrome. Pages sit on an off-white background (#F7F7F7) with near-black text (#1C1C1C). Type is set in Urbanist for headings, Public Sans for body copy, and Instrument Serif for accent lines. Nothing in the stylesheet is fixed: every colour, size, spacing step and duration is a theme setting that renders into a CSS custom property.

Upload the theme

The theme folder is named studionope-lumen. With the HubSpot CLI installed and authenticated:

hs upload studionope-lumen studionope-lumen --portal=<your-portal>

The first argument is the local folder, the second is the destination folder in the Design Manager. Keep them the same. Once the upload finishes the theme appears under Settings > Content > Themes.

While you edit locally, hs watch studionope-lumen studionope-lumen --portal=<your-portal> keeps the portal in sync on every save.

Set the theme settings

Open the theme and choose Edit theme settings. Work through Typography, Colors, Layout and Effects & motion first. Those four groups decide how the whole site looks, and a single edit moves every page at once.

Create a page

  1. Go to Content > Website Pages > Create and pick a Lumen template.
  2. Give the page an internal name and a URL slug.
  3. Click any section to open its fields in the right-hand sidebar. Headings, copy, images, video, links and per-section spacing are all there.
  4. Drag sections to reorder them, or delete the ones you do not need.
  5. Set the page title and meta description under Settings.
  6. Publish.

Every template arrives with sample copy and sample photography in place, so the layout works before you swap in your own.

Header and footer

The header and footer are global partials shared by every page, so you edit them once. The navigation and footer theme settings decide how each one is built. After changing a partial, republish the pages that use it.

Point the blog at the theme

Under Settings > Content > Blog, set the listing template to Lumen — Blog Listing and the post template to Lumen — Blog Post. Publish one post before reviewing the layout; an empty blog renders its empty state instead.

What lives where

PathContents
css/main.css imports _variables.css (the tokens rendered from theme settings) along with _normalize.css, _typography.css, _layout.css, _modules.css, _animations.css, _forms.css, _blog.css and _utilities.css.
js/main.jsScroll reveals, the stagger helper, the slide-in menu, count-up numbers and the motion kill-switch.
js/scroll-fx.jsSmooth scrolling, section stacking, parallax, the word-by-word heading reveal and the spiral carousel.
modules/Every drag-and-drop module. Each folder holds module.html, fields.json and meta.json.
templates/website-pages/, blog/, landing-pages/, system/, sections/, layouts/ and partials/.
fields.jsonThe theme settings schema: every setting described on this page.
theme.jsonTheme name, description, preview page and marketplace thumbnail.
images/Module icons, template previews and the demo photography.
02

Theme settings

Ten groups in one panel. Every value renders into a CSS custom property that the whole site reads.

Brand

brand.primary_color (#222222) and brand.secondary_color (#F7F7F7) feed HubSpot standard styles: link colour, focus rings, and anything HubSpot renders on its own. The layout does not read them directly. Keep them aligned with your palette and do the real work in Colors.

Typography

Changing the fonts

Three font fields drive the theme. Change the family on any one and every place it is used follows.

  • typography.heading_font — Urbanist. Every heading and display line. Renders as --mb-font-display.
  • typography.body_font — Public Sans. Paragraphs, lists, labels, navigation. Renders as --mb-font-body.
  • typography.accent_font — Instrument Serif. The serif line used inside display headings for emphasis. Renders as --mb-font-accent.

The base layout requests all three from Google Fonts by name, so a family you pick there loads without any further step. The colour picker on each font field sets the default colour for that role.

The fluid type scale

Headings scale with the width of the browser window rather than jumping at a breakpoint. typography.viewport_scale_base (1280) is the reference width, where a heading renders at exactly the size you typed. typography.viewport_scale_max (1920) is the width at which growth stops.

The heading sizes are the size at that reference width: fs_h1 (72), fs_h2 (42), fs_h3_lg (34), fs_h3 (22) and fs_h4 (19). Set fs_h1 to 60 and every H1 on the site gets smaller in proportion at every window size.

Fixed sizes

Smaller text does not scale: fs_kicker (18), fs_body (16), fs_xs (14), fs_micro (12) and fs_project_num (28). typography.font_size_base (18) is the root size the page inherits.

Weights, line height, letter spacing

fw_light (300), fw_regular (400) and fw_medium (500) are the three weights in use. Line heights run lh_tight (1.2) for large headings through lh_relaxed (1.6) for body copy. Letter spacing is entered in hundredths of an em, so ls_h1 at -2 means minus 0.02em, and ls_caps_lg at 10 is the wide tracking on small capitalised labels.

Colors

Surfaces

  • colors.bg_primary — the page background, #F7F7F7.
  • colors.surface_light — the white card surface, #FFFFFF.
  • colors.surface_warm — a muted surface for alternating sections, #ECEBE9.
  • colors.surface_warm_soft — a lighter muted surface, #E7E7E7. This is the card behind every system page.
  • colors.surface_dark — the near-black surface, #050505. The footer and the dark sections.

Text and lines

  • colors.text_primary#1C1C1C, everything on a light surface.
  • colors.text_inverse#F7F7F7, everything on a dark surface.
  • colors.text_muted#8A8A8A, captions, meta lines and supporting copy.
  • colors.border_color#1C1C1C, the base colour for every hairline. Borders combine this colour with the opacity settings in Effects, so a border is never a separate colour to keep in sync.
  • colors.accent_gold#222222. The single emphasis colour, used on hover and highlights. Set it to a real colour if you want one accent across the site.

Overlays

Each overlay is colour plus opacity in one field, so you set the tint and its strength together. colors.overlay_hero (black at 55%) sits over hero photography and video, overlay_sectors (50%) over section header media, overlay_menu_backdrop (60%) behind the open menu, menu_panel_color (#222222 at 97%) is the menu panel itself, card_overlay_bottom (65%) is the gradient at the foot of a project card, and shadow_color (40%) the shadow behind the number on a project card.

Making the site darker

Swap bg_primary to a dark value and text_primary to a light one, then set surface_light, surface_warm and surface_warm_soft to progressively lighter darks. Every module reads these tokens rather than its own colours, so the whole site follows.

Layout

layout.page_max_width is 9999 by default, which means content runs edge to edge. Lower it to hold the layout inside a fixed measure on very wide screens.

layout.gutter_pct (3), gutter_min (16) and gutter_max (200) set the space between content and the edge of the window: a percentage of the window width with a floor and a ceiling. Every section reads it as --mb-page-gutter, which is why the margins line up down the whole page.

layout.breakpoint_tablet (1023) and layout.breakpoint_mobile (640) are the two widths at which layouts reflow.

Spacing runs space_xs (4), space_sm (8), space_md (16), space_lg (24), space_xl (32), space_2xl (48), space_3xl (64) and space_4xl (96). Every gap in the theme is one of these steps.

Padding inside a card comes from pad_card_inner (64), pad_card_inner_mobile (32) and pad_card_block_mobile (40). Pills use pad_pill_x (22) and pad_pill_y (10). Projects and footer have their own top and bottom padding fields.

Photography needs room, so several sections have a height floor: min_hero_floor (520) and min_hero_cap (880) for heroes, plus floors for the section header, pitch media, mission media and sector cards.

layout.max_text_block (720) caps how wide a paragraph can run. max_panel_width (880) caps the slide-in menu panel. scroll_cue_size (60) is the round scroll cue at the foot of the hero.

Effects and motion

Corner radius

effects.default_radius is one preset that sets the roundness of everything at once: Square (0px, the shipped default), Subtle (8px), Rounded (16px), Soft (20px), Generous (28px), or Custom. Picking Custom hands control to radius_card (20), radius_card_lg (24) and radius_card_xl (30). Those three do nothing on any other preset.

Borders and tints

Hairlines are drawn from colors.border_color at three strengths: opacity_border_subtle (8), opacity_border_normal (12) and opacity_border_strong (18). effects.rule_strong_width (2) is the weight of the heavier rule the theme draws where a hairline is not enough. Muted copy uses opacity_text_muted (70) and opacity_text_softer, and small labels on a dark surface use opacity_kicker_dark.

Timings

duration_fast (180), duration_normal (220) and duration_slow (380) cover hovers and transitions, in milliseconds. effects.duration_reveal (800) is how long a section takes to fade in as it enters the screen. Raise it for a slower, heavier feel.

Reveal shape

  • effects.reveal_offset_y (28) — how far an element travels up as it appears.
  • effects.reveal_offset_x (32) — the sideways version.
  • effects.reveal_zoom (104) — the starting scale of an image reveal, as a percentage. At 104 the photograph starts slightly oversized and settles.
  • effects.word_reveal_dim (15) — the starting opacity of a word in the word-by-word heading reveal, as a percentage. At 15 unread words are faint and light up as you scroll. Raise it towards 100 to make the effect almost invisible.

Turning motion off

effects.enable_animations is on by default. Switch it off and the layout writes data-no-animate onto the page, which stops the smooth scrolling, the reveals, the word reveal, the parallax and the spiral carousel. Content is left fully visible. Visitors whose operating system is set to reduce motion get the same treatment with nothing set on your side.

Stacking order

effects.z_header (50) and effects.z_overlay (100) decide what sits above what. Raise them only if an embedded third-party widget insists on covering the header.

Buttons

buttons.cta_shape picks the shape used by every call to action: Circle, Pill, or Regular — a small-radius rectangle, which is what ships. cta_default_size (127) is the diameter of the circular CTA and only applies to that shape. cta_label_size (14) is the label size, cta_border_width (1) the outline weight on outlined buttons.

Forms

HubSpot forms are restyled so an embedded form reads as part of the page. forms.form_input_radius is Square, Rounded (8px) or Pill, and ships Square. form_input_border_color is #1C1C1C at 18%, form_input_focus_color the colour an input takes on focus, and form_input_bg the fill behind it. form_label_uppercase is on, which sets field labels in small capitals. form_button_match_cta is on, so the submit button takes the same shape as the rest of your calls to action; turn it off to keep submit buttons rectangular while your CTAs are circles.

Header

The header renders as a bar over the top of the page with a logo and a MENU button. The button opens a full-screen panel with the primary links and any sub-links beneath them. header.header_sticky is on, which keeps the bar visible as you scroll. header.pad_header_y (18) is the height of the bar, pad_panel (56) and pad_panel_x (64) the padding inside the open panel. Social icons sit in a round chip sized by social_icon_size (48) with the glyph at social_icon_glyph (22).

Navigation and Footer

navigation picks how the header is built: Navigation (Manual Links), the shipped default, with links written into the header partial; Navigation Menu (HubSpot Menu), the same header populated from a menu under Content > Navigation; or Drag and Drop, an empty area you compose yourself.

footer offers Footer, the shipped module, or Drag and Drop. The module renders a dark band with a wordmark, columns for Navigate, Contacts, Address and Socials, a hairline, then the copyright line and a legal link.

The Navigation module takes a light and a dark logo. Supply both and the header swaps between them so the logo stays readable whether the section behind it is a bright photograph or a dark one. Supply neither and the site name renders as text.

03

Page templates

Each template is a starting arrangement of modules with sample content. Keep it, edit it, or remove sections you do not need.

Website pages

TemplateModules, in order
Lumen — HomeLumen Hero, Featured Grid, Bending Cards, Statement with Lumen Stats beneath it in the same card, Why Work, Lumen FAQ, CTA Banner
Lumen — PortfolioLumen Hero, Featured Grid, Bending Cards, Featured Grid, CTA Banner
Lumen — Project DetailHero Statement, Section Block, Image Gallery, Stats Counter, Section Block, Before After, Section Block, Testimonials, Pillars Grid, Project Showcase, Mission Block
Lumen — ServicesLumen Hero, Bending Cards, Statement, Lumen Stats, Why Work, Lumen FAQ, CTA Banner
Lumen — Service DetailLumen Hero, Statement, Service Includes, Bending Cards, Featured Grid, Why Work, Lumen FAQ, CTA Banner, Service Pager
Lumen — PricingLumen Hero, Statement, Pricing Tiers, Pricing Add Ons, Service Includes, Lumen FAQ, CTA Banner
Lumen — GalleryHero Statement, Section Block, Image Gallery, Section Block, FAQ
Lumen — StudioLumen Hero, Statement, Lumen Stats, Lumen Team, Why Work, Lumen FAQ, CTA Banner
Lumen — ContactContact Split, on its own
Lumen — DocumentationPage Hero, Category List, a run of Docs Blocks, Lumen FAQ, CTA Banner. This page.

Working with them

  • Replace the hero media first. It sets the tone for everything below.
  • On Service Detail, set the Service Pager on each service page so visitors can move between services without going back.
  • Duplicate Project Detail for each project.
  • On Contact, point the form field at a HubSpot form you have already built.

Landing pages

Both landing pages extend templates/landing-pages/lp_layout.html, a chrome-free layout that drops the header and renders the Footer module directly, so a campaign page has one way out.

  • Lumen — LP Consultation — Lumen Hero, Why Work, Lumen Team, Lumen Anchor, Featured Grid, Lumen Anchor, Contact Form, Lumen FAQ, CTA Banner.
  • Lumen — LP Portrait Guide — Lumen Hero, Statement, Lumen Stats, Lumen Anchor, Why Work, Featured Grid, Lumen Anchor, Contact Form, Lumen FAQ, CTA Banner.

The Lumen Anchor above the form renders nothing visible. It exists so a button higher up the page can jump straight to the form, and it carries enough offset that the fixed header does not cover the landing point. Set its id in the module, then point the hero button at that id.

Blog

Lumen — Blog Listing is a masthead over a grid of post cards, then pagination. The masthead reads the page it is on: the main listing shows your journal title and intro, a topic URL shows the topic name, an author URL shows the author name. Each of those three states has its own kicker and intro line.

Lumen — Blog Post is a back link, the post header with date, author and reading time, the article body set to a comfortable measure, then a related-articles strip drawn from the same blog.

Every fixed string on both templates — the back links, the author label, the related heading, the reading-time suffix, the empty state, the pagination labels — is a text module you can edit in the page editor sidebar. Reading time is calculated from the post body. Set a featured image on every post; cards fall back to a plain wordmark tile without one.

System pages

Lumen ships templates for 404, 500, password prompt, search results, subscription preferences, subscriptions confirmation and unsubscribe. Assign them under Settings > Content > Pages > System pages.

Theme settings cannot hold free text and system pages have no drag-and-drop area, so every heading and paragraph on these pages is routed through the System Message module. Open a system page in the page editor and click the message block to edit the copy. All of them render inside the same card, which sits on colors.surface_warm_soft. The search results page uses the native HubSpot search input and results, styled to match.

Sections

Sections live in templates/sections/ and appear in the Sections drawer of the page editor. Each is a single section wrapping a module already filled in with sample content, so dragging one onto a page gives you something laid out rather than an empty block: Hero Statement, Testimonials, FAQ, Stats Counter, Project Showcase, Mission CTA and Image Gallery. Once dropped, a section is a normal module.

Layouts

Website, blog and system pages extend templates/layouts/base.html, which loads the fonts, the stylesheet, the two theme scripts and GSAP with ScrollTrigger and Lenis, then renders the global header and footer around the page. Landing pages extend templates/landing-pages/lp_layout.html.

04

Modules

Every section on every page is a module. They are grouped here by what they are for.

Heroes

Lumen Hero

The signature opening. A photograph or video that holds on screen for one full window height while the next section rises over the top of it. Takes a kicker, a headline with an accent word, a supporting line, two buttons and a scroll cue. The overlay is weighted towards the bottom so a white headline stays readable over a bright image. The content is visible the moment the page paints, so a slow connection never shows an empty hero.

Hero Statement

A full-bleed hero card with a kicker, headline, supporting copy, an optional button, an optional scroll cue, and a background image or video with per-instance overlay strength. Used on Gallery and Project Detail.

Page Hero

A quieter opening for a secondary page: kicker, headline, body and an optional button on one side, an image or video on the other. Used at the top of this page.

Showing work

Featured Grid

A centred heading over a full-bleed image grid with straight top and bottom edges at any number of tiles. Clicking a tile opens a full-screen lightbox above the header. The parallax speed is editable per tile.

Bending Cards

A spiral of photographs. An inner sticky window holds the section while the ring rotates and travels upward, so the images spiral through the view as you scroll. The front-facing card stays flat so it stays readable. If the animation library fails to load, the section falls back to a row of images.

Image Gallery

Images and video in a bento, grid or masonry pattern, with optional captions, hover zoom and a lightbox. Better than Featured Grid when the images are mixed sizes or need captions.

Project Showcase

Project cards with a title, a location line and an image, laid out as a bento grid. Use it for related work at the foot of a case study.

Pinned Stack

Full-window photo panels that stack on top of each other as you scroll, each with a slow background drift. For a run of images that should feel like a sequence rather than a grid.

Before After

A drag-to-reveal comparison between two images, horizontal or vertical, with your own labels and a starting position.

Copy and structure

Statement

An editorial block: a kicker, an oversized statement that lights up word by word as you scroll, an accent phrase, a supporting line and a portrait image. On Home and Studio the Lumen Stats band sits directly beneath it inside the same card so the two read as one section.

Why Work

A sticky section where a numbered list runs down the left and a photograph on the right crossfades as the active item changes with scroll. Keep the list short: every item adds roughly a window of scrolling.

Section Block

Image on one side and copy on the other, or copy alone. Kicker, headline, body and an optional button, on a light card, a dark card or the page background.

Pillars Grid

Short titled paragraphs in two, three, four or six columns. For values, guarantees or what is included.

Service Includes

A centred heading over a row of short titled paragraphs, set on the section background with no cards or icons. Used on Service Detail and Pricing.

Category List

A numbered list of linked titles in one, two or three columns. The contents list near the top of this page is one.

Docs Block

A documentation section: eyebrow and heading on the left, long-form rich text on the right, with an anchor id so a contents list can link to it. Subheadings, lists, tables and code are styled by the module. Every block on this page below the contents list is one.

Proof and people

Lumen Stats

A minimal row of numbers that count up when the row comes into view. Sits under a Statement as a band rather than a section of its own.

Stats Counter

The standalone version: numbers with an optional prefix and suffix, a label and a supporting line, in a three- or four-column layout with optional dividers, light or dark.

Lumen Reviews

A rating-led wall of short reviews. One large average score, monochrome stars, a strip of the sources the reviews came from, then the entries with reviewer, date and source. Two layouts: a column wall, or a single-line score with the reviews listed beneath. It can average the score from the entries itself, or take a figure you set, and it emits review structured data behind a toggle. Reach for Testimonials instead when you want a few long quotes read one at a time.

Testimonials

Client quotes with a photo, role, company and star rating. Autoplay speed, alignment and maximum width are editable.

Lumen Team

The editorial roster: a portrait, a name, a role, a line about what the person handles on a shoot, and a hairline list of their duties.

Team Grid

A simpler alternative: portrait, name, role and social links in a two-, three- or four-column grid, portrait or square crop, with the icons appearing on hover.

Client Logos

A logo strip, either marching as a marquee or static in rows, with pause on hover and adjustable speed and direction.

Enquiries and closing sections

Contact Split

The whole contact page in one module. Copy, studio details, an optional booking block and the enquiry form scroll down one half; a column of photographs runs down the other. The photographs are a crossfade rather than a scroll: appearance.dwell is how long each shot holds and appearance.hold how much of that is spent at full strength before the next one fades in. appearance.surface and appearance.split set the tone and the column ratio. Below the tablet breakpoint the photographs stop being sticky and stack under the copy.

Contact Form

A two-column section: copy, contact details and social links on one side, a HubSpot form on the other. Used on both landing pages.

Contact CTA

An overline, an oversized headline, an underlined email address and a dark button. A compact way to close a page that does not need a full banner.

CTA Banner

A full-bleed photograph or video with a large heading and two buttons, the image drifting slowly as you scroll. This is the section that sits between the FAQ and the footer on most templates.

CTA Circle

The circular outline button on its own, for dropping anywhere in a page.

Mission Block

Image on one side, copy and a button on the other. A quieter closing section, used on Project Detail.

Lumen FAQ

A display heading on the left and an accordion on the right. The FAQ used across the site, and the one holding the questions at the foot of this page.

FAQ

A centred accordion built on native expand-and-collapse markup, so it works with a keyboard and a screen reader without extra scripting. Used on Gallery.

Service Pager

A full-bleed previous and next pager at the foot of a service page. Two large images side by side, each with a label, the service name and a link. The whole panel is clickable.

Lumen Anchor

An invisible scroll target. Anchor markup written between drag-and-drop sections is stripped by the editor, so anchors have to come from a module. Place one in the same column as the section you want to jump to.

Site chrome and utilities

Navigation and Navigation Menu

The header bar plus the slide-in menu overlay, with nested sub-items and animated carets. Both take a light logo, a dark logo and the site name. Navigation holds its links in the header partial; Navigation Menu reads a HubSpot menu. The navigation theme setting picks between them.

Footer

The dark closing band: a wordmark, columns for Navigate, Contacts, Address and Socials, a hairline, then the copyright line and legal links.

System Message

The editable copy block on every system page. It emits only the inside of the system card, so the card and its spacing stay in the template, which matters because several of those pages also embed a native HubSpot module inside the same card.

Blog modules

MB Blog Hero, MB Blog Posts, MB Blog Pagination, MB Blog Post Header and MB Related Posts are available in the picker for building a custom listing or post layout. The shipped blog templates render their markup directly.

Also in the library

Sector Cards, Pitch Block, Services List, Process Steps, Office Locations, Job Listings and Docs ship with the theme but are not placed on any template. They are in the module picker if you build a page that needs one.

05

Scroll and motion

Two theme scripts own every effect. Modules mark their markup and write no scroll code of their own.

The pieces

  • Smooth scrolling — the page eases rather than jumping. Lenis interpolates the real scroll position, so sticky sections and the fixed header keep working normally.
  • Reveals — content fades in and lifts as it enters the window, once, then stays put. Nothing hides again on the way back up.
  • Stacking sections — a section holds on screen for one window height while the next one scrolls up and covers it. That is the effect on the home hero and on Why Work.
  • Word reveal — headings start faint and each word reaches full strength as you scroll past it.
  • Parallax — background photographs drift at a different speed from the page. The image is scaled up in the same movement so its edge never shows.
  • Count-up — numbers in the stats modules run up from zero when they come into view.
  • Spiral carousel — the Bending Cards ring rotating and rising as you scroll.

What runs it

js/main.js handles the reveals, the stagger helper, the menu and the counters. js/scroll-fx.js owns smooth scrolling, section stacking, parallax, the word reveal and the carousel. The base layout loads GSAP, ScrollTrigger and Lenis from a CDN alongside them. Because the effects live in two files rather than in each module, motion behaves the same on every page and turning it off turns all of it off.

The attribute contract

These are the marks a module makes. You do not write them by hand in a rich-text field; they are listed so the behaviour on the page is explainable.

AttributeWhat it does
data-stackMarks a section as a deck layer. Layers are numbered in the order they appear on the page, and each one must paint its own opaque background so the section beneath it is hidden as it is covered.
data-stack-holdA section that holds for one window height and is then covered, with data-stack-pin on the sticky inner layer. The Lumen Hero and Why Work use it.
data-fx=wordsThe word-by-word reveal. Every heading on the page takes it automatically; a block marked data-fx-skip opts out, which is how the long copy on this page stays at full strength.
data-revealThe fade-and-lift entrance. The theme walks every section on load and marks the content blocks inside it, so a page built entirely from modules still animates.
data-staggerOn a container, so its children arrive one after another instead of together. The theme numbers them as the page loads and cycles the numbering on a long list, so the effect stays a ripple rather than a queue.
data-parallaxThe drift speed as a fraction of page speed, on the image, with data-parallax-scope on the frame it is cropped inside.

Reveals are automatic

Headings are skipped by the reveal because the word reveal already handles them, and anything already being moved by script — carousel faces, parallax images, sticky layers — is skipped so two effects never fight over the same element.

Reveal styles

A module can ask for a different entrance. lift is the card entrance used by repeater items: starts lower, slightly scaled down and softly blurred, then rises and sharpens. image-zoom starts scaled up by effects.reveal_zoom and eases back to true size. slide-left enters from the right by effects.reveal_offset_x. clip is a curtain: the element is masked from the bottom and the mask opens downward, over effects.duration_slow. All four collapse to the finished state for a visitor who has asked their operating system to reduce motion.

Parallax, and what breaks it

An element carrying data-parallax must not also have a CSS transform, or a transition on transform. The engine writes an inline transform onto that element on every frame: a transform in the stylesheet loses the fight, and a transition on transform smears the drift into a lag. Express hover and other states on that element through opacity or a filter instead, and put any transform you need on a wrapper.

Tuning it

Slow everything down with effects.duration_reveal. Shorten the travel with effects.reveal_offset_y. Soften the word reveal by raising effects.word_reveal_dim: it is the starting opacity of an unread word, so a higher number means less contrast between read and unread text. Switch effects.enable_animations off to stop all of it.

06

Best practices

What the layout expects from your photographs, your copy and your markup.

Image sizes

  • Hero backgrounds — at least 2400px wide. They run full-bleed on a large monitor and a smaller file will look soft.
  • Featured Grid and Project Showcase tiles — landscape, around 1600px wide. The grid crops to fill, so keep the subject away from the edges.
  • Portraits in Lumen Team — a tall crop, at least 1200px on the long edge.
  • Testimonial and review photos — square, around 800px.

Weight

Compress everything before upload. A hero can afford to be heavier than a grid tile, but a page carrying a dozen uncompressed exports will feel slow no matter how well the motion is tuned. HubSpot optimises on upload, and a pass through a compressor before that helps more.

Video

Use an MP4 around 1080p with a poster image. A 4K file will stall or refuse to start on a phone. The poster is what visitors see while the video loads, so pick a frame that reads as a still photograph on its own.

Copy lengths

  • Hero headline — short. The word reveal animates one word at a time, and a long line loses its rhythm.
  • Statement — one sentence, set large. It is the loudest line on the page.
  • Section Block headline — a short phrase. The column is capped, so a long headline wraps.
  • Section Block body — a paragraph or two. Beyond that the image beside it runs out of height.
  • Pillar and Service Includes titles — a few words each, kept a consistent length so the row stays even.
  • Review and testimonial text — short enough to read at a glance.
  • Kickers — the small capitalised line above a heading is a label, not a sentence. One or two words.

Headings

Give every page one H1, in the hero, and step down from there. The theme sets the sizes, so use the heading level that matches the structure of the page and let the type scale handle how big it looks.

Accessibility

Every effect respects the operating-system reduce-motion setting, and effects.enable_animations switches all of it off site-wide. Content never depends on an animation to become visible: if a script fails, everything is still on the page.

The shipped palette is near-black on off-white, which clears contrast requirements comfortably. If you recolour, check text against its surface, and check white headings against your hero photograph in particular. Raising the opacity on colors.overlay_hero is the fastest fix for a hero that has become hard to read.

The menu, the accordions and the lightbox all work from the keyboard, and focus outlines are visible on every interactive element. Leave them in place.

Write alt text on every image. The lightbox reads it, search engines read it, and a screen reader has nothing else to work with. Write link text that makes sense read on its own.

Before you launch

  1. Replace every demo photograph with your own.
  2. Set the page title and meta description on each page.
  3. Assign the system pages and the blog templates.
  4. Check the site at the tablet and mobile breakpoints.
  5. Publish the theme settings, then republish any page that uses the header or footer partial.

Things that come up

  • Open Edit theme settings > Typography. typography.heading_font sets every heading, typography.body_font every paragraph and label, and typography.accent_font the serif line used inside display headings. The base layout requests all three from Google Fonts by name, so a family you pick loads without a further step. Sizes are separate: the heading sizes are the numbers in the same group, and they scale with the window from typography.viewport_scale_base.

  • Check effects.enable_animations first. When it is off, the layout writes data-no-animate onto the page and every effect stops. Then check your own machine: if reduce-motion is switched on in your operating system, the theme honours it and you see a still page while everyone else sees the motion. Then check the page: motion needs GSAP, ScrollTrigger and Lenis, which the layout loads from a CDN. If an extension or a strict content policy blocks those requests the theme degrades on purpose — scrolling stays native, sections still stack, and everything is visible.

  • Stacking sections are layered in the order they appear on the page, and each one paints its own opaque background. If you can see through a section, the covering section has no background of its own: set one in its style fields. If there is a gap, remember that a holding section pauses for one window height before it is covered, so two holding sections in a row read as a long pause. Put a normal section between them, or use one per page.

  • Hero height sits between layout.min_hero_floor (520) and layout.min_hero_cap (880). Raise the floor if it looks short on a laptop, lower the cap if it looks endless on a tall monitor. The header is fixed over the page, so a section that starts flush with the top of the window can slide under it. Sections that need to clear it already do; if you build a new page and the first heading is hidden, add top padding to that section or open the page with a hero.

  • Use the Lumen Anchor module rather than writing an anchor into a rich-text field. It carries the offset that keeps the header off the landing point, and anchor markup written directly between drag-and-drop sections is stripped by the editor. The Docs Block module carries its own id and the same offset, which is what the contents list at the top of this page links to.

  • Inputs read forms.form_input_bg, forms.form_input_border_color and forms.form_input_focus_color. If you have recoloured the site, set those three to match. If the submit button is the wrong shape, forms.form_button_match_cta makes it follow buttons.cta_shape — turn it off to keep it rectangular. If a long submit label is clipped inside a circular button, shorten the label in the HubSpot form or raise buttons.cta_default_size. If the form is empty, pick a form in the module field; build it in HubSpot first.

  • Theme settings are saved and published separately from pages: use Publish changes in the theme settings panel, then hard-refresh. Some values are per-section rather than site-wide — section padding, overlay strength on an individual hero, and column counts live on the module in the page editor. And effects.radius_card does nothing unless effects.default_radius is set to Custom; on any other preset the preset supplies the values. After editing the header or footer partial, republish the pages that use it.

Photographer packing down after a shoot

Something here not covered? Tell us what you were looking for