# Cynosure Design System > A design system for Cynosure Lutronic web properties. Components are built > with Bootstrap 5, Handlebars.js, SCSS, and Vite. The system is authored in > the Handoff platform and can be compiled into WordPress Gutenberg blocks > using the handoff-wordpress CLI. ## Stack - Templates: Handlebars.js (.hbs) - CSS: Bootstrap 5.3.5 + custom SCSS; design tokens as CSS custom properties - JavaScript: jQuery 3.7.1 (legacy components) + Vanilla JS ES modules; Vite bundler - Fonts: Juana (display headings), Open Sans (body) - Figma project: 3GcQn3eA8Kg9kprYXBXksv ## Design Tokens Tokens are exported from Figma and compiled to CSS custom properties. Token files: - Colors: /api/component/tokens/css/colors.css - Typography: /api/component/tokens/css/typography.css - Effects: /api/component/tokens/css/effects.css - Buttons: /api/component/tokens/css/button.css - Alerts: /api/component/tokens/css/alert.css Key color tokens: - --color-primary-orange: #ff4713 - --color-primary-orange-light: #ff6c42 - --color-primary-orange-dark: #cc390f - --color-secondary-purple: #6f2eff - --color-secondary-purple-light: #8c58ff - --color-tertiary-pink: #db3381 - --color-tertiary-plumb: #361f50 - --color-neutral-gray-100: #f4f4f4 - --color-neutral-gray-300: #d0d2d3 - --color-neutral-gray-600: #696969 - --color-neutral-gray-900: #231f20 - --color-neutral-white: #ffffff - --color-text-hard: #000000 - --color-text-base: rgba(0, 0, 0, .8) - --color-text-soft: #555555 - --color-text-muted: rgba(85, 85, 85, .8) - --color-text-hard-invert: #ffffff - --color-text-base-invert: rgba(255, 255, 255, .85) - --color-border-base: rgba(105, 105, 105, .15) - --color-gradient-primary: linear-gradient(90deg, #ff4713 0%, #dc001b 100%) - --color-gradient-energy-blends: linear-gradient(90deg, #db3381 0%, #361f50 100%) - --color-gradient-hero-dark: linear-gradient(90deg, #434a50 0%, #231f20 100%) - --color-extra-success: #49c781 - --color-extra-warning: #e6e448 - --color-extra-danger: #f25454 - --color-extra-info: #c0e1f0 Key typography tokens: - --font-family-juana: 'Juana' - --font-family-open-sans: 'Open Sans' - --typography-heading-1-font-size: 48px / weight 400 / line-height 1.4 - --typography-heading-2-font-size: 36px / weight 400 - --typography-heading-3-font-size: 28px / weight 400 - --typography-heading-4-font-size: 24px / weight 300 Key effect tokens: - --effect-shadow-base-300: 0px 1px 2px rgba(0, 0, 0, .15) - --effect-shadow-base-500: 0px 2px 8px rgba(0, 0, 0, .1) - --effect-shadow-base-700: 0px 4px 4px rgba(0, 0, 0, .25) ## Blocks - about: About section with team content and brand story - accordion-simple: Expandable content accordion (jQuery slideToggle) - banner: Rotating image/text hero banner (Slick Carousel .js-default-slider) - before-after: Before/after image comparison carousel - button-strip: Row of CTA buttons - callout: Highlighted callout with optional accordion and SVG icons - comparison-slider: Side-by-side image comparison with draggable divider - contact-columns: Contact information in a column layout - content: General content area with optional accordion sections - content-bio-list: Speaker/team bio list with expandable biography panels - content-sidebar-callout: Content with sidebar callout panel - cta-provider: Provider search CTA with Select2 filter dropdowns - cta-simple: Simple call-to-action section - cta-two-column: Two-column CTA layout - divider: Visual section divider - download: Gated document download with Magnific Popup modal and Select2 - downloads-columns: Multi-column download grid with popup gates and filters - downloads-list: Filterable download list with popup gates - downloads-split: Split layout download section with popup gates and filters - event-upcoming-callout: Upcoming event callout card with SVG icons - events-upcoming: Upcoming events listing with SVG icons - events-upcoming-asset: Upcoming events with downloadable assets - events-upcoming-list-sidebar: Filterable events list with sidebar and Select2 - feature: Feature section with optional accordion detail panels - footer: Global site footer with Select2 dropdowns and SVG social icons - footer-compact: Minimal footer with copyright - full-screen-video: Full-screen video section with SVG icons - full-width-video: Full-width video embed with SVG icons - grid-four-column: Four-column content grid - grid-three-column: Three-column content grid with Select2 filter - grid-three-column-intro: Three-column grid with intro header - grid-three-column-nav: Three-column grid with filterable navigation - header: Global site header (sticky nav, search, mobile nav, offcanvas, jump nav, SVG) - header-compact: Compact header variant - header-lander: Landing page header variant - hero-article: Article page hero with SVG category icons - hero-basic: Standard page hero with SVG icons - hero-background-video: Hero with background video - hero-contact: Contact page hero with provider finder, popups, Select2, SVG - hero-cta: Hero with prominent CTA - hero-cta-split: Split hero layout with image and CTA - hero-news: News/blog hero with Select2 filter and SVG icons - hero-product: Product page hero with jump navigation and SVG icons - hero-search: Site search hero with SVG icons - hero-search-provider: Provider search hero with Select2 and SVG icons - listing-pagination: Pagination controls for listing pages - map-full-width: Full-width Google Map embed - map-with-sidebar: Google Map with sidebar content - notification: Dismissible site notification banner (cookie-based via header.js) - post-featured: Single featured post card - posts-featured: Featured posts in Slick Carousel article card slider - posts-latest: Latest posts with Select2 category/tag filter - posts-latest-sidebar-intro: Latest posts with sidebar and intro header - product-showcase: Product showcase grid - testimonial-slider: Testimonial Slick Carousel (.js-default-slider with dots) - testimonial-wysiwyg: WYSIWYG testimonial block - testimonials: Testimonials grid with SVG quote icons - text-single-column: Single-column text content - text-split: Two-column split text layout - text-split-image: Split layout with text and image - text-split-video: Split layout with text and video ## Element Components - alert: Bootstrap 5 alert / notification - badge: Label badge - button: Single button element - buttons: Button group with SVG icon support - checkbox: Checkbox input - date: Date display element - download-card: Downloadable file card - input: Text input field - modal: Bootstrap 5 modal dialog - pagination: Pagination controls - radio: Radio button input - select: Styled Select2 select dropdown - side-nav: Sidebar navigation - switch: Toggle switch input - testimonial: Single testimonial element - tooltip: Bootstrap 5 tooltip ## Shared JavaScript Utilities All utilities live in src/handoff/js/components/ and are imported by blocks via script.js. Vite deduplicates — each utility appears once in the final bundle regardless of how many blocks import it. - accordion.js: .c-accordion__toggle — jQuery slide expand/collapse; one panel at a time - default-slider.js: .js-default-slider, .js-default-slider-alt — Slick Carousel presets - article-card-slider.js: .js-article-card-slider — Slick Carousel for post cards - carousel-content.js: .js-carousel-content — content panel carousel - header.js: .c-header__bottom (sticky), .c-notification__close (banner dismiss + cookie) - main-nav.js: .c-main-nav — primary navigation dropdowns - mobile-nav.js: .c-mobile-nav — mobile nav drawer - hamburger-icon.js: .c-hamburger — hamburger/X icon toggle - search-bar.js: .c-site-search — site search expand/collapse - offcanvas.js: .c-offcanvas — Bootstrap 5 offcanvas panel - jump-nav.js: .c-jump-nav — sticky in-page anchor navigation - tabs.js: .js-toggle-tab, .c-tabs — tab switching with scroll-to - selects.js: .c-select select, .event-form-select, .c-provider-finder__select — Select2 - popup.js: .js-open-content-popup, .js-open-video, .js-open-wistia-video-popup — Magnific Popup - reveal.js: .will-slide-right, .will-slide-left, .will-fade-in — ScrollReveal animations - parallax.js: [data-parallax] — scroll-based parallax - smooth-scroll.js: .js-smooth-scroll — smooth anchor scrolling - comparison-slider.js: .js-comparison-slider — before/after divider (jquery.twentytwenty) - speaker-card.js: .c-speaker-card — bio expand/collapse - observer.js: [data-observe] — IntersectionObserver utility - gravity-forms.js: .gform_wrapper — Gravity Forms field enhancements - consent.js: .c-consent — cookie consent banner - svg-inline-loader.js (utility): img[src$=".svg"] — replaces SVG with inline ## Component File Structure Each block lives at src/handoff/blocks/{name}/ and contains: - {name}.js — Handoff config: id, title, description, figma, properties schema, previews - template.hbs — Handlebars template using Bootstrap 5 utility classes and c- BEM classes - style.scss — Minimal component SCSS using CSS custom property tokens; c- prefix required - script.js — JSDoc-annotated @shared imports and/or custom multi-instance JavaScript ## Key Conventions Templates: - Use Bootstrap 5 utility classes (d-flex, gap-3, fw-semibold, text-muted, py-5, etc.) - Use c-{block-name} BEM prefix for all custom classes - Reference properties: {{properties.field}} for text, {{{properties.body}}} for richtext - Loop: {{#each properties.items}} ... {{/each}} - Conditionals: {{#if properties.show_cta}} ... {{/if}} SCSS: - Class prefix: .c-{block-name}, .c-{block-name}__element, .c-{block-name}--modifier - Use var(--color-primary-orange) not #ff4713 - Never @import main.scss in component style.scss (Handoff injects it) - Path alias @public → public/, @export → exported/3GcQn3eA8Kg9kprYXBXksv/ JavaScript: - All script.js files require a JSDoc @shared annotation or custom multi-instance logic - Multi-instance: document.querySelectorAll('[data-component="..."]').forEach(block => {...}) - Scope all DOM queries to block element, never document.getElementById - Use class="js-*" selectors, never id="*" for JavaScript hooks ## WordPress Integration The handoff-wordpress CLI compiles Handoff components into WordPress Gutenberg blocks. - Install: cd examples/handoff-wordpress && npm install && npm run build - Config: handoff-wp.config.json (see handoff-wp.config.example.json) - Fetch: handoff-wordpress fetch - Docs: /guidelines/wordpress Enqueue the shared JS bundle in WordPress: https://cynosure.handoff.com/api/component/main.js ## Documentation - Guidelines overview: /guidelines - JavaScript architecture: /guidelines/javascript - Component scripts: /guidelines/javascript/component-scripts - Shared utilities: /guidelines/javascript/shared-utilities - Slick Carousel: /guidelines/javascript/slick - Select2: /guidelines/javascript/selects - Magnific Popup: /guidelines/javascript/popup - CSS & SCSS: /guidelines/scss - WordPress integration: /guidelines/wordpress - Accessibility: /guidelines/accessibility - AI & LLMs overview: /guidelines/ai - Ingesting into LLMs: /guidelines/ai/overview - AGENTS.md & llms.txt: /guidelines/ai/agents - llms.txt format: /guidelines/ai/llms-txt - WordPress with AI: /guidelines/ai/wordpress - Color foundations: /foundations/colors - Typography foundations: /foundations/typography - Effects foundations: /foundations/effects-guidelines ## Build Commands - npm run start — development server with live reload (port 4000) - npm run build:components — build component JS/CSS bundle - npm run build:app — build documentation site - npm run fetch — pull latest design tokens from Figma - npm run validate:components — validate all component configs