The Linden manual.
Everything you need to install, configure, customise, and ship the Linden Family Health theme. One scroll, complete reference.
What ships in the box.
Linden Family Health is a premium HubSpot CMS theme for primary care clinics, family medicine practices, pediatric offices, and small multi-specialty groups. Every visual property is editable from theme settings — no code required for day-to-day operation.
Inventory
- 10 website page templates — home, about, doctors, doctor-profile, services, pricing, insurance, contact, faq, legal, docs.
- 2 landing-page templates — book-a-visit lead-gen, gated PDF download.
- Full blog system — listing template with hero/search/topics/authors + post template with related-posts + back-to-archive nav.
- 21 drag-and-drop modules — every one field-driven, every visual property bound to theme tokens.
- 2 global partials — Navigation Pro header and Footer Pro footer, both fully editable.
- System pages — 404, 500, password prompt, unsubscribe.
- 161 theme settings across 11 groups — colors, typography, layout, effects, buttons, forms, header, icons, footer, brand, navigation.
Stack
- HubSpot CMS — drag-and-drop page editor, HubL templating, native form integration.
- CSS custom properties — every style flows from
fields.json→ theme settings →_variables.css→ component CSS. No SCSS compile, no Tailwind purge, no rebuild step. - Vanilla JavaScript — 336 lines in
js/main.jsdrives scroll reveals (IntersectionObserver), hero parallax, animated counters, mobile menu, header scroll-state, word-split headlines. All RAF-throttled and reduced-motion safe. - Swiper 11 — loaded from CDN only when Testimonials carousel is on the page.
- Google Fonts — auto-loaded by HubSpot from the font fields. Default pairing: Fraunces (display) + Sora (body).
Four steps from purchase to first page.
-
1. Buy + activate
Purchase from the HubSpot Marketplace. The theme installs into your portal automatically and appears under Settings > Website > Themes > Linden Family Health. Click Activate to make it the default.
-
2. (Optional) CLI
Install the HubSpot CLI (
npm install -g @hubspot/cli), authenticate withhs init, then runhs upload studionope-for-medical studionope-for-medicalfrom a local copy if you want CLI-level control. Skip this if you only need the UI. -
3. Brand kit
Open Settings > Account > Brand Kit. Upload your clinic logo (PNG or SVG with transparent bg). It appears automatically in Navigation Pro and Footer Pro via HubSpot's brand_settings.
-
4. Theme settings
Open Settings > Website > Themes > Linden > Edit theme settings. Set colors, fonts, spacings, radii. Every change re-renders the CSS on the next page load — no rebuild.
Going live in 30 minutes.
Step A — Wire navigation
Open templates/partials/header.html. The menu_items array drives the entire top nav. Each item has a type of link (single URL), dropdown (icon + title + description rows), or mega (multi-column grid). Replace the example items with your own routes. Re-upload with hs upload.
For dropdown items, the icon property uses HubSpot's icon picker — pass { "name": "stethoscope", "type": "SOLID", "unicode": "f0f1" }. Note that HubSpot ships Font Awesome 5.0.10 — use known FA5 icon names only.
If you prefer HubSpot's UI menu picker over the HubL array, set theme.navigation = navigation_menu in theme settings.
Step B — Wire footer
Open templates/partials/footer.html. The columns array holds up to 4 link columns. The contact block holds address, phone, email. The social block holds Instagram, Facebook, LinkedIn, etc. (uses HubSpot's social icons via the platform key). The bottom block holds copyright + legal links.
Step C — Create your first page
Go to Marketing > Website > Website Pages > Create > Website page. Pick the Linden template that matches your need (Home, About, Doctors, etc). The page opens in the drag-and-drop editor with placeholder content from the template — replace section by section. Click Publish when done.
Step D — Set up the blog
Go to Marketing > Website > Blog > Create blog. Set the slug (e.g. linden/blog) and language. In Blog templates, assign:
- Listing template →
studionope-for-medical/templates/blog/listing.html - Post template →
studionope-for-medical/templates/blog/post.html
Create an author under Marketing > Website > Blog > Authors. Then create posts under Create > Blog post.
Step E — Connect domain
Once content is in place, connect your live domain under Settings > Website > Domains & URLs. Republish everything. The CDN may cache for ~30 seconds before serving the new bundle.
Eleven groups, 161 fields, zero hardcoded values.
Every visual property in the theme is editable from Settings > Website > Themes > Linden > Edit theme settings. The groups below are the top-level sections you will see in the panel sidebar.
-
Brand
Primary + secondary brand colors. Read by HubSpot's standard widgets (form focus states, default links). Set these to your clinic palette first.
-
Typography
Heading font + body font (Google Fonts auto-loaded). Type scale from H1 → micro. Font weights light/regular/medium. Line-heights tight/snug/relaxed. Letter-spacing for caps + headings.
-
Layout
Page gutter min, content max-width (1440px default), Pro container width (for nav/footer), spacing scale xs–4xl, card padding inner + mobile, header pad, section gap, pill x/y padding, min-heights.
-
Effects
Border radius (square, card, card-lg, pill, hero-card). XL shadow Y/blur/opacity. Map filter sepia/saturate/hue/brightness. Eight opacity tokens (text-muted, border-normal, kicker-on-dark, etc). Animation master toggle.
-
Buttons
CTA shape — circle (editorial default), pill (rounded rectangle), or square. Drives the
.mb-cta-circlerendering site-wide. -
Forms
Form button match-CTA toggle. When on, every HubSpot form submit button matches the primary button 1:1.
-
Colors
Page background, surface light/dark/warm, text + text-inverse, accent cream + cream-hover, accent gold, overlay-hero, overlay-sectors.
-
Header
Sticky toggle, Y padding, pill height, brand-mark size, nav-link size, Nav Pro blur strength, Nav Pro bg opacity, dropdown bg opacity, mega-menu icon size + opacity, Material Symbols size.
-
Icons
Material Symbols style: outlined (default), rounded, or sharp. Applies to all built-in nav and footer system icons.
-
Footer
Footer padding top + bottom. Pad-footer-top and pad-footer-bottom in pixels.
-
Navigation
Navigation type — Navigation Pro (default mega-menu pill), HubSpot menu picker, or DnD area.
-
Animations
Inside Effects group — enable_animations toggle disables ALL motion site-wide. Honored by every
[data-reveal]element + the JS hero-parallax + counters.
Eleven palette tokens — set once, cascades everywhere.
The color system is the single most important set of theme settings to configure. Every other tinted UI element composes from these via color-mix(in srgb, …) with the opacity tokens.
- bg — Page background. Default
#faf6f0(warm ivory). - surface_light — Cards, modals, dropdown panels. Default
#ffffff. - surface_dark — Dark card variant, hero overlays. Default
#1a1f2e. - surface_warm + surface_warm_soft — Map placeholder backgrounds, project-card gradients.
- text — Body and heading color. Default
#1a1f2e(near-black). - text_inverse — Text on dark backgrounds. Default
#ffffff. - accent_cream + accent_cream_hover — Primary CTA pill background and its hover state. Default
#FFF4C0/#FFEB99. - accent_gold — Star ratings, success indicators, validation error color.
- overlay_hero — Dark wash placed over hero background images for legibility. Color + opacity controllable.
- overlay_sectors — Sectors header overlay tint.
How opacity tokens work: instead of shipping faded variants of each color, Linden composes them on the fly via color-mix(in srgb, var(--mb-text) 70%, transparent). The 70% comes from theme.effects.opacity_text_muted. Lower that one value and every muted text + border across the site updates in lockstep. No need to define 12 shades of text — just adjust the opacity once.
Two fonts, fluid scale, every size editable.
Linden ships with Fraunces (display serif, weights 300–600) for headings, kickers, and editorial copy, and Sora (geometric grotesque sans, weights 300–500) for body text and UI. Both load automatically from Google Fonts via HubSpot's load_external_fonts on the font fields.
Swapping fonts
Open theme.typography.heading_font and theme.typography.body_font. Pick any Google Font. The Google Fonts URL in base.html rebuilds dynamically — no link tag to maintain. To use a non-Google font, you would need to add your own <link> tag in base.html head.
Type scale
Linden uses a CSS clamp() fluid scale based on viewport width. Set the size at the scaling base (default 1280px) and the font auto-scales smaller below and larger above (up to viewport_scale_max, default 1920px).
- fs_h1 @ 1280 — Hero headlines. Default 44px (scales 32–88px).
- fs_h2 @ 1280 — Section headlines. Default 28px.
- fs_h3_lg @ 1280 — Featured H3s. Default 24px.
- fs_h3 @ 1280 — Default H3. Default 18px.
- fs_h4 @ 1280 — H4 / small heading. Default 16px.
- fs_body — Body copy. Fixed 15px (does not scale).
- fs_kicker — Kicker labels + nav links. Fixed 13px.
- fs_xs — Button labels, captions. Fixed 12px.
- fs_micro — Chips, badges, validation errors. Fixed 11px.
Weights, line-heights, letter-spacing
Three weight tokens — fw_light (300), fw_regular (400), fw_medium (500). Three line-heights — lh_tight (1.2 for H1), lh_snug (1.4 default), lh_relaxed (1.7 for long-form blog body). Letter-spacing — ls_h1 (tight for headlines), ls_caps_sm + ls_caps_md (for small-caps labels and kickers).
One gutter formula, one container width, eight spacing tokens.
Page gutter
The horizontal space between content and the viewport edge is computed as:
--mb-page-gutter: max(gutter_min, calc((100vw - content_max_width) / 2))
Below the content max-width (1440px default), the gutter is a fixed minimum (24px default). Above it, the extra width is split equally between the gutters so content stays centered without ever exceeding the max-width. This means content reads the same on a 13" laptop and a 32" monitor.
Container widths
- content_max_width — Page content. Default 1440px.
- pro_container_width — Navigation Pro + Footer Pro inner container. Default 1280px.
- max_text_block — Centered text blocks (this paragraph). Default 880px.
- max_panel_width — Side panels (mobile menu overlay). Default 480px.
Spacing scale
Every gap, padding, and margin uses one of these tokens — no inline pixel values anywhere:
- space_xs — 4px. Icon gap, tight inline gap.
- space_sm — 8px. Pill padding, button gap.
- space_md — 12px. Standard component gap.
- space_lg — 18px. Card content gap.
- space_xl — 24px. Block gap.
- space_2xl — 36px. Major content group gap.
- space_3xl — 48px. Section-internal spacing.
- space_4xl — 64px. Largest spacing.
Sections are separated by section_gap (default 72px). Cards have an internal pad_card_inner (default 40px desktop, 24px mobile). Pills have pad_pill_x + pad_pill_y. Headers have pad_header_y. All in theme settings.
Radii, shadows, opacity, animations, map filters.
Border radius
- radius_block_square — Inputs, small cards. Default 8px.
- radius_card — Section cards, mission cards. Default 24px.
- radius_card_lg — Larger card variants. Default 32px.
- radius_pill — CTA pills, nav buttons. Default 999px.
- radius_hero_card — Hero card. Default 0 (full-bleed).
- radius_block_round — Round-corner block variant. Default 24px.
Shadow
One shadow token --shadow-xl, composed from three fields:
- shadow_xl_y — Y offset (default 8px).
- shadow_xl_blur — Blur radius (default 24px).
- shadow_xl_opacity — Color opacity 0–60 (default 12%).
Result: 0 8px 24px color-mix(in srgb, var(--mb-text) 12%, transparent). To make shadows more pronounced raise the opacity; to soften them raise the blur and lower the Y.
Opacity tokens
Eight opacity values control every faded UI element:
- opacity_text_muted — Muted body text. Default 70.
- opacity_text_softer — Secondary text. Default 85.
- opacity_kicker_dark — Kicker on dark bg. Default 85.
- opacity_border_subtle — Hairline borders. Default 8.
- opacity_border_normal — Default borders. Default 12.
- opacity_border_strong — Emphasized borders. Default 18.
- opacity_white_chip — Translucent chips on dark. Default 6.
- opacity_social_chip — Social icon chip bg. Default 8.
Map filter (Office Locations)
The embedded Google Maps tiles can be tinted to match your palette:
- map_filter_sepia 0–1. Sepia wash. Default 0 (raw map).
- map_filter_saturate 0–200%. Default 100%.
- map_filter_hue -180 to +180 deg. Default 0.
- map_filter_brightness 30–150%. Default 100%.
Animations master toggle
enable_animations — Master switch for scroll-reveals, hero parallax, word-split, counters. When off, every [data-reveal] element renders without motion and the JS skips registration.
Ten templates for the public site.
Each template lives in templates/website-pages/ and ships with placeholder content tailored to a primary-care clinic. Edit any section in the DnD page editor without touching code.
home.html
Eight sections in order: Hero Statement (full-viewport with cream-pill CTA), Sector Cards (4-up services), Mission Block (about + photo), Team Grid (4-up doctors), Pillars Grid (why-us 4-up), Testimonials (carousel), FAQ (5 items), Mission Block (final CTA). Use this as the front door.
about.html
Seven sections: Hero with optional video background, Stats Counter (4-up by-the-numbers), Sector Cards (story chapters), Pillars Grid (six values, 3-up), Team Grid, history timeline (rendered as 6-up Pillars Grid for the pill-tag look), Mission Block final CTA. Use to tell the practice story.
doctors.html
Six sections: Hero with video, full Team Grid with long bios (anchor_id="team" for /linden/about#team deep-link), Pillars Grid (how-we-practice 3-up), Stats Counter, Testimonials, Mission Block find-your-doctor CTA.
doctor-profile.html
Nine sections for individual clinician pages: Hero with portrait + name + role, Mission Block (bio + clinic image), Pillars Grid (credentials 3-up — education / residency / board cert / licensure / hospital privileges / memberships), Sector Cards (4-up areas of focus), Stats Counter (practice in numbers), Testimonials specific to this doctor, Pillars Grid (publications + talks 3-up), FAQ doctor-specific, Mission Block book CTA. One template, copy + tweak for each doctor.
services.html
Service catalog: Sector Cards header, in-depth Services List with rich-text per item, FAQ, Mission Block final CTA.
pricing.html
Six sections: Hero, Pillars Grid (three pricing tiers 3-up with featured-flag), Services List (itemized cash prices), Mission Block insurance, FAQ billing, Mission Block final CTA.
insurance.html
In-network carriers, common copay/deductible scenarios, FAQ, contact link.
contact.html
Contact Form as the hero (left text + right form, no separate hero block above), Office Locations cards with Google Maps embed, contact-specific FAQ.
faq.html
Long-form FAQ archive grouped by topic — multiple FAQ modules stacked (new-patients, billing, telehealth, hours, after-hours, refills).
legal.html
Privacy Policy + HIPAA Notice + Accessibility + Terms of Use, with anchor TOC at the top.
Lead-gen funnels, blog system, error pages.
Landing pages — templates/landing-pages/
lp_consultation.html — Book-a-first-visit funnel. Seven sections: Hero with anchor CTA, Pillars Grid (what is included), Pitch Block (why we built Linden), condensed Team Grid, Testimonials, Contact Form (anchored, captures booking), FAQ for objections.
lp_report.html — Gated PDF download. Seven sections: Hero, Mission Block (author credibility anchor), Pillars Grid (six chapters preview), Pitch Block (pull-quote), Stats Counter, Contact Form (gated download), FAQ download-objection.
Blog — templates/blog/
listing.html — Listing page template. Three sections: MB Blog Hero (with search, topics chips, authors chips), MB Blog Posts (1/2/3-column grid), MB Blog Pagination.
post.html — Individual post template. Wraps in <article> with: MB Blog Post Header (hero), content.post_body, MB Related Posts (3 related). Includes back-to-archive nav.
System pages — templates/system/
404.html — Centered error page. Edit copy directly in template.
500.html — Same shape as 404.
password-prompt.html — HubSpot password gate styled to match theme.
backup_unsubscribe.html — Email unsubscribe page.
Twelve content modules with field-by-field detail.
Hero Statement
Full-viewport hero. Fields: kicker, headline, subhead (richtext), show_cta, cta_label, cta_url, show_scroll_cue, overlay_opacity 0–80, bg_image, bg_video_url + bg_video_poster (video overrides image when set).
Mission Block
Two-column text + image. Fields: kicker, headline, body_text (richtext), show_cta + cta_label + cta_url, overlap_hero (overlap previous hero by 36px when true), image.
Sector Cards
Card grid for services. Fields: header_kicker, header_headline, header_body (richtext), header_image, show_cta + cta_label + cta_url, items (repeater 1–8 with title / body_text / image per card). Grid auto-sizes 2/3/4 columns.
Pillars Grid
Flexible value-prop grid. Fields: kicker, headline, body_text (richtext), columns ("2"/"3"/"4"/"6"), scheme (light/dark), pillars (repeater 1–12 with title / body_text / optional cta_label + cta_url / featured flag).
Team Grid
Clinician grid. Fields: kicker, headline, anchor_id (deep-link target), columns (2/3/4), members (repeater with image / title / role / body_text per member).
Testimonials
Patient quote carousel. Fields: kicker, headline, body_text, testimonials (repeater with quote / star_rating 0–5 / author_name / author_role / author_company / author_photo), style object (max_width narrow/medium/wide, alignment left/center, autoplay bool, autoplay_speed ms). Swiper-powered when multiple quotes.
FAQ
Accordion. Fields: kicker, headline, body_text, items (repeater 1–20 with question + answer richtext), style.open_first, style.layout (split/full).
Stats Counter
Animated counters. Fields: kicker, headline, body_text, stats (repeater 2–6 with value / display_value override / prefix / suffix / stat_label / description), layout object (columns 2/3/4, alignment, scheme, dividers bool).
Services List
Itemized list. Fields: kicker, lead_headline, lead_body, services (repeater with title + body_text richtext), show_cta + cta_label + cta_url.
Pitch Block
Editorial pull-quote. Fields: kicker, headline (use \n for editorial line break — encoded as in templates), body_text, show_cta + cta_label + cta_url, image.
Section Block
Generic text + image block (used in this docs page). Fields: kicker, headline, body_text (richtext), layout (text_only / text_left / text_right), scheme (bare / light / dark), show_cta + cta_label + cta_url, image.
Page Hero
Smaller hero for inner pages. Fields: same shape as Hero Statement plus automatic --mb-header-clearance padding-top.
Nine more: forms, locations, navigation, footer, blog.
Contact Form
Two-column module — left kicker + headline + body, right HubSpot form. Fields: kicker, headline, body_text, hubspot_form (HubSpot form picker — pick any form you have built).
Office Locations
Multi-office cards with maps. Fields: kicker, headline, body_text, columns (1/2/3), show_maps (renders inline Google Maps iframe per office), offices (repeater with title / address richtext / phone / email / hours / map_query).
Navigation Pro
The global header pill nav. Lives at templates/partials/header.html. Fields: logo, menu_items (repeater with type link/dropdown/mega), search (enable + placeholder), ctas (repeater with style primary/secondary), settings (sticky from theme.header.header_sticky, blur_bg, top_margin, language_switcher), style (width container/full/compact, background, text_color, shadow, border_radius, padding). Mega menu rendered with HubSpot icon picker per item (Font Awesome 5.0.10).
Footer Pro
The global footer. Lives at templates/partials/footer.html. Fields: brand (logo, tagline), columns (up to 4, each with title + links repeater), contact (title + address + phone + email), social (links repeater with platform key), bottom (copyright + legal_links repeater + language_switcher), style (layout, background, padding, show_divider).
MB Blog Hero
Listing hero. Fields: bg_media_type (image/video), bg_image, bg_video_url + bg_video_poster, kicker, headline, body_text, plus per-view variants (tag_kicker + tag_headline_prefix + tag_body, author_kicker + author_headline_prefix + author_body, all_kicker + all_headline + all_body), show_search + search_placeholder, show_topics + topics_label + topics_limit, show_authors + authors_label + authors_limit.
MB Blog Posts
Post list. Fields: posts_per_row (1/2/3), show_excerpt, show_date, show_author, show_read_more, excerpt_length (chars), read_more_label.
MB Blog Pagination
Page-number pagination. Fields: prev_label, next_label, max_visible_pages.
MB Blog Post Header
Hero on individual post pages. Reads featured image, title, author, date, category, reading time from HubSpot context. Fields: fallback_bg_image, bg_overlay_opacity, show_kicker + show_meta + show_back_link, back_link_label, reading_time_suffix.
MB Related Posts
Bottom-of-post related grid. Fields: heading, cta_label, post_count (2/3/4), show_date, show_author, show_excerpt, show_read_more, excerpt_length, read_more_label.
Eight principles for editing without breaking the system.
1. Token-first editing
Never hardcode a color, size, or radius in custom HTML you drop into a rich-text field. If you need a specific shade, use the existing accent or text-muted token via inline style: style="color: var(--mb-accent-gold);". This keeps your edits intact when the operator changes the theme palette.
2. Stick to the type scale
Use H1 once per page (the hero). Section headings are H2. Sub-headings inside rich text are H3. Avoid H4 unless deeply nested. The CSS already styles these — never set font-size inline.
3. Section rhythm
Every page is a stack of dnd_section blocks. Don't insert custom <section> markup at the top level of templates — it bypasses the DnD editor. Use modules instead.
4. Cards over rectangles
When in doubt, choose a module that renders cards (Pillars Grid, Sector Cards, Team Grid) over a custom rich-text grid. Cards stay aligned, responsive, and theme-driven automatically.
5. One CTA per fold
Don't stack three competing CTAs in the hero. The cream-pill primary CTA should be the obvious next action. Secondary actions belong further down the page in Mission Block or Pitch Block.
6. Images are 16:9 or portrait
Sector Cards and Sector Cards expect landscape 3:2 or 16:9. Team Grid expects portrait 3:4. Hero backgrounds: 16:9 or wider, minimum 2400×1350 to stay sharp on retina.
7. Respect the cream
The cream accent is a once-per-page color — Book a Visit CTA, primary booking buttons. Don't paint section backgrounds cream — use surface_light or surface_warm instead. Overusing the accent dilutes its signal.
8. Test mobile
Every module is responsive but check key pages in HubSpot's device-preview at 375px (small phone), 768px (tablet), and 1440px (laptop). The hero on home, the mega-menu in the nav, and the contact form layout are the most common pain points.
Common edits, step-by-step.
-
Change brand color
Open Theme settings > Colors. Edit accent_cream (CTAs) or text (everything else). Save. Hard-refresh the page (~30s CDN propagation). All buttons + hover states + borders cascade automatically.
-
Swap the logo
Upload your logo at Settings > Account > Brand Kit. Both header + footer pick it up via HubSpot brand_settings. For a custom file path, edit
templates/partials/header.html+footer.htmland change thelogo_studioset var. -
Add a menu item
Open
templates/partials/header.html. Add an entry to themenu_itemsarray. Type 'link' for plain URL, 'dropdown' for icon+title+description rows, 'mega' for multi-column grid. Re-upload viahs upload. -
Add a new doctor profile
Marketing > Website Pages > Create page from the Doctor Profile template. Update hero portrait + name + role, bio body_text, credentials cards, areas of focus, stats, testimonials, FAQ. Add the profile URL to the Doctors dropdown in header.html.
-
Add a blog post
Marketing > Website > Blog > Create > Blog post. The post inherits
templates/blog/post.htmlautomatically. Pick an author, set featured image, write body. Publish. -
Change page gutter
Theme settings > Layout > gutter_min (24px default). The page-gutter formula auto-fills excess width above content_max_width — only change gutter_min if you want tighter or looser horizontal padding on smaller screens.
-
Disable a section
In the DnD editor, hover the section, click the trash icon. Sections can be re-added by dragging the module back from the right sidebar. Or hide via section-level visibility settings.
-
Add a new language
Create a translated variation under Marketing > Website > Multi-language. Set theme.header.language_switcher = true. Nav + footer will show the language picker.
-
Override a single CSS rule
Don't edit theme CSS directly — your changes will be lost on theme update. Instead use HubSpot's Settings > Website > Pages > Site footer HTML to add a scoped
<style>block. Or fork the theme into your own copy.
Subtle, performant, accessible.
All animations are driven by js/main.js (336 lines, vanilla JS). Five effects in total:
1. Scroll reveals
Every element with data-reveal fades in + translates up when scrolled into view. Driven by IntersectionObserver — one observer, observes every element, fires once per element. Stagger via data-delay="N" (N = multiplier of 0.15s).
2. Hero parallax
Hero background image translates down and scales out as you scroll past. JS sets --hero-progress from 0 to 1 on the hero element. CSS transforms the image with translateY(0..12%) scale(1.06..1). RAF-throttled, IntersectionObserver-gated so it stops doing work when the hero is off-screen.
3. Word-split headings
Add data-split="words" to any heading. The JS splits the text into per-word spans and reveals them with stagger.
4. Number counters
Stats Counter module animates each data-counter element from 0 to its target on scroll-in. Reads data-counter-prefix + data-counter-suffix for formatting. Counts only once.
5. Dropdown morph
Navigation Pro mega-menu uses a single dropdown wrapper that morphs in width and height between menu items via CSS transitions — feels like a continuous panel rather than discrete dropdowns.
Reduced motion
All animations short-circuit when prefers-reduced-motion: reduce is set in the OS, or when theme.effects.enable_animations is off. In that case the JS skips registration and elements render in their final state immediately.
Performance
All three scroll listeners are { passive: true } and RAF-throttled via a ticking flag — max one update per frame each. Counters use data-counter-done to skip already-run elements. Total scroll-handler cost per frame: ~1 getBoundingClientRect + a handful of arithmetic operations. Lighthouse Performance score stays above 90.
How the pieces talk to each other.
The theme's plumbing is three global partials and one bridge stylesheet:
templates/partials/header.html
Renders Navigation Pro. Owns menu structure, mega-menu items + icons, search toggle, cream-pill CTA. Switch nav type via theme.navigation: navigation_pro (default), navigation_menu (HubSpot menu picker), dnd (full DnD area for fully custom nav).
templates/partials/footer.html
Renders Footer Pro. Owns 4 link columns, brand block with tagline, social links, contact (address/phone/email), copyright, legal links. Switch via theme.footer: footer_pro (default) or dnd.
css/_pro-bridge.css
HubL-rendered stylesheet that maps Linden's --mb-* tokens to the --color-*, --space-*, --font-*, --nav-*, --footer-* variables expected by Navigation Pro and Footer Pro (they came from studio-nope-theme originally). This is what makes those modules visually match the rest of the theme without forking them. If you edit a token in fields.json, you don't need to touch the bridge — it reads tokens via HubL at render time.
The blog
Listing template at templates/blog/listing.html, post template at templates/blog/post.html. Both extend the same base.html layout, so navigation and footer wiring is consistent with the rest of the site.
css/main.css
Entry point. Imports the partial CSS files in this exact order: _variables → _pro-bridge → _normalize → _typography → _layout → _modules → _forms → _animations → _utilities. The order matters — variables must exist before they're consumed, bridge must come before component CSS so module-level tokens are available, animations come after modules so reveals can compose with module-specific transforms.
Every common gotcha and its fix.
-
I changed a theme setting but nothing updated.
HubSpot caches the rendered CSS for ~30 seconds on the CDN. Hard-refresh (Cmd-Shift-R / Ctrl-F5). If the change still isn't there, re-publish the page from Design Manager — that forces a fresh bundle.
-
My fonts aren't loading.
Check that the font name in theme.typography.heading_font matches a Google Fonts family exactly (case-sensitive, spaces preserved). HubSpot auto-loads the configured variant via the font field — you don't need a manual
<link>tag. -
Hero video isn't playing on mobile.
Mobile browsers block autoplay video without
mutedandplaysinline. The Hero Statement module sets both already. If it still doesn't play: check the video file is reachable, under 10MB, and served from a CORS-allowed origin (HubFS is fine). -
Navigation overlaps the first section on a page without a hero.
Use the Page Hero module on pages that need clearance for the fixed nav. The CSS applies
padding-top: var(--mb-header-clearance)on first-of-type non-hero sections automatically. The clearance is calculated as--mb-space-4xl + --mb-space-2xl(~100px). -
How do I link a new blog post in the menu?
Open
templates/partials/header.html, add an entry to themenu_itemsarray, re-upload viahs upload. The mega menu is HubL-driven — no UI editing needed. -
The CTA button looks different on different pages.
Every button uses the same shared rule block in
css/_pro-bridge.css. Primary buttons render the cream pill, secondary the outlined variant, form submits match primary 1:1. If a button looks wrong, inspect it — check the HTML class is.primary-button,.secondary-button, or it's aninput[type=submit]. Anything else won't pick up the shared rule. -
Mega menu icons are invisible.
HubSpot ships Font Awesome 5.0.10 only. Not every modern FA name is in that set. Use known FA5 icons:
stethoscope,heart,user-md,medkit,flask,video,clipboard,tags,shield-alt,question-circle. Set the icon opacity via theme.header.nav_pro_icon_opacity (60% default). -
Blog listing renders with a different theme's classes.
The auto-created blog listing page persists with its first template assignment. PATCHing listingTemplatePath on the blog config doesn't update the listing page render. Fix: delete + recreate the blog with both
itemTemplatePathandlistingTemplatePathset in the create call. -
Page edits don't show up after template changes.
HubSpot caches the DnD widget tree on the page object when it's first created. Editing the template doesn't update existing pages. Fix: delete + recreate the page, OR edit each section directly in the page editor.
-
I see HubL parse errors with backslash in my content.
HubL doesn't support
\"or\'escapes in parameter values. Inside HTML rich-text content, use HTML entities:",',\. Picking the opposite outer quote style (single outside, double inside) also works. -
Search bar in nav alters the bar height when opened.
The search input must be
height: var(--mb-space-2xl)to match menu links. Bridge enforces this; if you forked the bridge, keep the rule. Also the bar itself is locked toheight: calc(var(--mb-space-2xl) + var(--mb-space-md) * 2). -
Form submit button looks different from primary CTA.
Form submit + primary button now share the exact same rule block in
_forms.css. Toggle theme.forms.form_button_match_cta ON to enable the match; OFF gives form submits a darker fill so they stand out from inline content.
Every demo URL on this site.
Site pages
/linden/homepage→ home.html/linden/about→ about.html/linden/doctors→ doctors.html/linden/doctor/john-wang→ doctor-profile.html/linden/services→ services.html/linden/pricing→ pricing.html/linden/insurance→ insurance.html/linden/contact→ contact.html/linden/faq→ faq.html/linden/legal→ legal.html/linden/docs→ docs.html (this page)
Landing pages
/linden/book-visit→ lp_consultation.html/linden/insurance-guide→ lp_report.html
Blog
/linden/blog→ blog/listing.html/linden/blog/{post-slug}→ blog/post.html
We are one email away.
If something in this documentation is unclear, broken, or out of date — email us. We will fix it and credit you in the changelog. Support is included with every theme license, indefinitely.