{"slug":"circuit","name":"Circuit – Strength & Conditioning Gym","version":"1.1.0","category":"local business","priceCents":2400,"description":"Circuit is a gym website template built in Tailwind and React for an independent strength-and-conditioning gym or boutique studio, and the freelancers and agencies who build sites for them. Seven routes ship: the home slab, the weekly schedule as a compact tick-row strip, the programme grid, one class rendered at full scale, the coach roster, the membership tier table, and a living component styleguide. Its signature is the roll sheet: every class is a fixed number of ruled lines, set by the room's own hard integer capacity, filled top to bottom in booking order, with a dashed rule crossing the sheet at the session's own start time — names above it carry an arrival stamp and a checkmark, names below it carry only the stamp. rollFor() computes every line from one fixture and throws at build time on an oversold session, a membership tier booked into a room it cannot access, or a coach or room double-booked anywhere in the week, so a class cannot go live with numbers that do not add up. No day-by-week calendar grid and no to-scale floor plan appear anywhere in the theme — the roll sheet and its compact strip are the only schedule visualisations it ships. The palette is dark-first: an ink-navy primary the sheet is signed in, a turf-green accent for the room's own floor-marking paint and the checked-in mark, in a near-black room lit only by the one bright, paper-coloured sheet. Fixtures are one spine: Ashgrove Barbell Club, a strength-and-conditioning gym in a converted 1930s tram depot in Fishponds, Bristol — two rooms, three coaches, three membership tiers and fourteen sessions a week, and every number on every route resolves through the same array.","summary":"A gym website template tailwind react with a roll sheet that fills line by line against real room capacity, tiers gated to the rooms they cover.","tags":["gym website template tailwind react","fitness website template nextjs","gym landing page tailwind template","strength training studio website template","boutique gym website template react"],"accent_mode":"second-hue","palette":{"bg":"#101218","surface":"#1b1e27","accent":"#14b34a","text":"#eef0f2","line":"#262930"},"darkMode":true,"pages":[{"path":"/","title":"Fourteen classes a week. Ten lines each.","sections":["masthead","hero-sheet","programs-overview","membership-teaser","coach-spotlight","location-hours","join-cta","footer"]},{"path":"/schedule","title":"This week's sheets","sections":["masthead","week-index","room-filter","sheet-strip-grid","legend","footer"]},{"path":"/programs","title":"What we coach","sections":["masthead","programs-intro","program-grid","program-detail-band","programs-faq","footer"]},{"path":"/class","title":"Tuesday 06:00 · Platform Room","sections":["masthead","class-header","full-sheet","coach-note","related-classes","footer"]},{"path":"/coaches","title":"Coaching staff","sections":["masthead","coach-roster","coach-bio-detail","certifications-band","footer"]},{"path":"/membership","title":"Membership","sections":["masthead","tier-table","tier-detail","policy-terms","join-form","footer"]},{"path":"/components","title":"The parts, unassembled","sections":["masthead","hero-sheet","programs-overview","membership-teaser","coach-spotlight","location-hours","join-cta","week-index","room-filter","sheet-strip-grid","legend","programs-intro","program-grid","program-detail-band","programs-faq","class-header","full-sheet","coach-note","related-classes","coach-roster","coach-bio-detail","certifications-band","tier-table","tier-detail","policy-terms","join-form","footer"]}],"components":[{"name":"masthead","file":"src/components/masthead.tsx","renders":"The site header: wordmark, primary navigation with aria-current on the open route, mode toggle, and a compact menu that closes on Escape"},{"name":"hero-sheet","file":"src/components/hero-sheet.tsx","renders":"Hero archetype A1: the H1, the CTA and its proof over a full-bleed depot plate whose eight frames advance with the reader's scroll, with the roll sheet overlaid on it live from Tuesday 06:00 Platform Room"},{"name":"programs-overview","file":"src/components/programs-overview.tsx","renders":"Three programme cards, each led by a plate of the apparatus that class runs on, linking to /programs"},{"name":"membership-teaser","file":"src/components/membership-teaser.tsx","renders":"The three tiers at a glance over a full-bleed plate of the depot floor, room access stated plainly, linking to /membership"},{"name":"coach-spotlight","file":"src/components/coach-spotlight.tsx","renders":"One coach introduced by name and role, linking to the full roster"},{"name":"location-hours","file":"src/components/location-hours.tsx","renders":"The depot's address, opening hours and a directions link"},{"name":"join-cta","file":"src/components/join-cta.tsx","renders":"One primary action naming the drop-in fee and the two membership tiers"},{"name":"footer","file":"src/components/footer.tsx","renders":"Colophon: wordmark, route links, address and hours"},{"name":"week-index","file":"src/components/week-index.tsx","renders":"The opener for /schedule: a day-by-day count of sessions, no calendar grid"},{"name":"room-filter","file":"src/components/room-filter.tsx","renders":"Filter chips for room and class type, composing the vendored filter-chip part"},{"name":"sheet-strip-grid","file":"src/components/sheet-strip-grid.tsx","renders":"Every session's compact tick strip for the week, filtered by room-filter's state"},{"name":"legend","file":"src/components/legend.tsx","renders":"What a filled tick, an open tick and the cutoff mean, stated once"},{"name":"programs-intro","file":"src/components/programs-intro.tsx","renders":"The opener for /programs: what the club actually trains, in one paragraph"},{"name":"program-grid","file":"src/components/program-grid.tsx","renders":"The three class types — Strength, Conditioning, Mobility — with the coach and room each runs in"},{"name":"program-detail-band","file":"src/components/program-detail-band.tsx","renders":"The equipment-detail photograph naming real apparatus, as supporting content rather than a floor plan"},{"name":"programs-faq","file":"src/components/programs-faq.tsx","renders":"Five questions a prospective member asks first, as disclosures"},{"name":"class-header","file":"src/components/class-header.tsx","renders":"The opener for /class: the session's day, time, room, coach and class type"},{"name":"full-sheet","file":"src/components/full-sheet.tsx","renders":"The oversized moment: every line of the room's capacity, named, timestamped, the dashed cutoff rule drawn, N lines left at the foot"},{"name":"coach-note","file":"src/components/coach-note.tsx","renders":"A line from the session's own coach on what the class covers"},{"name":"related-classes","file":"src/components/related-classes.tsx","renders":"Two other sessions of the same class type, as compact strips"},{"name":"coach-roster","file":"src/components/coach-roster.tsx","renders":"The three coaches ruled like a roster: role, certifications and weekly session count"},{"name":"coach-bio-detail","file":"src/components/coach-bio-detail.tsx","renders":"One coach at depth — portrait, bio and the sessions she runs this week"},{"name":"certifications-band","file":"src/components/certifications-band.tsx","renders":"Every certification held across the coaching staff, in one ruled list"},{"name":"tier-table","file":"src/components/tier-table.tsx","renders":"The three membership tiers as a table, room access resolved against roomAccess rather than typed twice"},{"name":"tier-detail","file":"src/components/tier-detail.tsx","renders":"The vendored variant-selector composed as the tier picker, each option's includes and excludes shown as it is chosen"},{"name":"policy-terms","file":"src/components/policy-terms.tsx","renders":"Cancellation, freeze and guest-pass terms, stated plainly"},{"name":"join-form","file":"src/components/join-form.tsx","renders":"The enquiry form: the vendored form and form-error-summary parts composed into a five-field intake with native constraints and a receipt"},{"name":"ui/button","file":"src/components/ui/button.tsx","renders":"Primary, secondary and ghost variants with hover, active, pending and disabled states"},{"name":"ui/badge","file":"src/components/ui/badge.tsx","renders":"Eyebrow, class-type chip and neutral fact tag"},{"name":"ui/card","file":"src/components/ui/card.tsx","renders":"The flat, bordered card every grid and roster row composes from"},{"name":"ui/field","file":"src/components/ui/field.tsx","renders":"Vendored library part (field): label, description, invalid and disabled states on a computed --field-border"},{"name":"ui/select","file":"src/components/ui/select.tsx","renders":"A native select styled to the theme's tokens, for the enquiry form's room and tier questions"},{"name":"ui/input","file":"src/components/ui/input.tsx","renders":"The text input recipe shared by the enquiry form's name, email and phone fields"},{"name":"ui/checkbox","file":"src/components/ui/checkbox.tsx","renders":"The enquiry form's consent control, native, with a visible focus ring"},{"name":"ui/tabs","file":"src/components/ui/tabs.tsx","renders":"Vendored library part (tabs): the sheet register and coach-presentation variant switches on /components"},{"name":"ui/accordion-disclosure","file":"src/components/ui/accordion-disclosure.tsx","renders":"Vendored library part (accordion-disclosure): the FAQ disclosures on /programs and the compact nav menu"},{"name":"ui/sheet-line","file":"src/components/ui/sheet-line.tsx","renders":"The signature primitive: one ruled row of the roll sheet, filled or open, with the cutoff's dashed rule and checkmark"},{"name":"ui/tag","file":"src/components/ui/tag.tsx","renders":"A neutral fact tag: room name, class type, or certification"},{"name":"ui/avatar","file":"src/components/ui/avatar.tsx","renders":"A coach's generated portrait, cropped square or 3:4, with a text-initial fallback"},{"name":"ui/nav","file":"src/components/ui/nav.tsx","renders":"The primary navigation list shared by the masthead and its compact menu"},{"name":"ui/mode-toggle","file":"src/components/ui/mode-toggle.tsx","renders":"Light and dark flip, applied to the .tt-circuit wrapper or the document root"},{"name":"ui/lift-sequence","file":"src/components/ui/lift-sequence.tsx","renders":"The hero's eight-frame lift, one frame visible, indexed by scroll position; CSS scroll timelines drive it where they exist and this is the fallback where they do not"},{"name":"ui/tier-gate-badge","file":"src/components/ui/tier-gate-badge.tsx","renders":"A room-access indicator: which membership tiers can book a given room, resolved from roomAccess"},{"name":"ui/inline-alert","file":"src/components/ui/inline-alert.tsx","renders":"A neutral, positive or critical inline message, used by the enquiry form's receipt and validation summary"},{"name":"ui/footer-nav","file":"src/components/ui/footer-nav.tsx","renders":"The footer's route list and legal line"},{"name":"ui/form","file":"src/components/ui/form.tsx","renders":"Vendored library part (form): the submit flow as one panel — a busy fieldset that refuses a second send and a named receipt focus lands on, composed by join-form"},{"name":"ui/form-error-summary","file":"src/components/ui/form-error-summary.tsx","renders":"Vendored library part (form-error-summary): the refused-answers panel, a counted heading, one link per failed field, composed by join-form"},{"name":"ui/dialog","file":"src/components/ui/dialog.tsx","renders":"Vendored library part (dialog), filled to the theme's tokens and unmounted — no shipped route needs a confirmation layer"},{"name":"ui/tooltip","file":"src/components/ui/tooltip.tsx","renders":"Vendored library part (tooltip), filled to the theme's tokens and unmounted — no shipped route needs a hover disclosure"},{"name":"ui/filter-chip","file":"src/components/ui/filter-chip.tsx","renders":"Vendored library part (filter-chip): the applied, removable room filter on /schedule, composed by room-filter"},{"name":"ui/variant-selector","file":"src/components/ui/variant-selector.tsx","renders":"Vendored library part (variant-selector): the /membership tier picker, each option's includes and excludes shown on selection, composed by tier-detail"}],"tokens":{"--background":"#101218","--foreground":"#eef0f2","--card":"#1b1e27","--card-foreground":"#eef0f2","--secondary":"#21242b","--secondary-foreground":"#eef0f2","--muted":"#1d1f26","--muted-foreground":"#8b939f","--border":"#262930","--primary":"#6b74c9","--primary-foreground":"#08090d","--primary-hover":"#7c86dd","--primary-active":"#8e99f1","--accent":"#14b34a","--accent-foreground":"#06210f","--ring":"#eef0f2","--field":"#20232c","--field-border":"#7e8086","--control-border":"#8d8f95","--selection":"#262a4b","--selection-foreground":"#eef0f2","--selection-border":"#7079c1","--link":"#7c86dd","--link-hover":"#8e99f1","--positive":"#53be70","--positive-soft":"#132417","--positive-border":"#3f8a54","--warning":"#e9ab2b","--warning-soft":"#271d0c","--warning-border":"#ad7f26","--critical":"#fd736d","--critical-soft":"#2f1816","--critical-border":"#c0564f","--info":"#68b7ed","--info-soft":"#15212a","--info-border":"#4c86ac","--shadow-color":"#05060a","--sheet-paper":"#fdf6e8","--sheet-paper-edge":"#d9c9a6","--sheet-rule":"#c7b898","--sheet-ink":"#1a2247","--sheet-muted":"#6b6455","--sheet-accent":"#0c9c3d","--sheet-cutoff":"#7d1f1f","--radius":"0.375rem","--text-caption":"0.75rem","--leading-caption":"1.4","--text-small":"0.875rem","--leading-small":"1.45","--text-body":"1rem","--leading-body":"1.55","--text-lead":"1.125rem","--leading-lead":"1.6","--text-d1":"1.5rem","--leading-d1":"1.25","--tracking-d1":"-0.01em","--text-d2":"2rem","--leading-d2":"1.2","--tracking-d2":"-0.015em","--text-d3":"clamp(2rem, 1.6rem + 2vw, 2.6875rem)","--leading-d3":"1.15","--tracking-d3":"-0.02em","--text-d4":"clamp(2.375rem, 1.6rem + 3.9vw, 3.5625rem)","--leading-d4":"1.1","--tracking-d4":"-0.025em","--tracking-label":"0.08em","--weight-display":"400","--font-display":"var(--font-circuit-display), ui-sans-serif, system-ui, sans-serif","--font-text":"var(--font-circuit-text), ui-sans-serif, system-ui, sans-serif","--font-sans":"var(--font-text)","--font-mono":"var(--font-circuit-mono), ui-monospace, 'Courier New', monospace"},"tokensDark":{"--background":"#101218","--foreground":"#eef0f2","--card":"#1b1e27","--card-foreground":"#eef0f2","--secondary":"#21242b","--secondary-foreground":"#eef0f2","--muted":"#1d1f26","--muted-foreground":"#8b939f","--border":"#262930","--primary":"#6b74c9","--primary-foreground":"#08090d","--primary-hover":"#7c86dd","--primary-active":"#8e99f1","--accent":"#14b34a","--accent-foreground":"#06210f","--ring":"#eef0f2","--field":"#20232c","--field-border":"#7e8086","--control-border":"#8d8f95","--selection":"#262a4b","--selection-foreground":"#eef0f2","--selection-border":"#7079c1","--link":"#7c86dd","--link-hover":"#8e99f1","--positive":"#53be70","--positive-soft":"#132417","--positive-border":"#3f8a54","--warning":"#e9ab2b","--warning-soft":"#271d0c","--warning-border":"#ad7f26","--critical":"#fd736d","--critical-soft":"#2f1816","--critical-border":"#c0564f","--info":"#68b7ed","--info-soft":"#15212a","--info-border":"#4c86ac","--shadow-color":"#05060a","--sheet-paper":"#fdf6e8","--sheet-paper-edge":"#d9c9a6","--sheet-rule":"#c7b898","--sheet-ink":"#1a2247","--sheet-muted":"#6b6455","--sheet-accent":"#0c9c3d","--sheet-cutoff":"#7d1f1f","--radius":"0.375rem","--text-caption":"0.75rem","--leading-caption":"1.4","--text-small":"0.875rem","--leading-small":"1.45","--text-body":"1rem","--leading-body":"1.55","--text-lead":"1.125rem","--leading-lead":"1.6","--text-d1":"1.5rem","--leading-d1":"1.25","--tracking-d1":"-0.01em","--text-d2":"2rem","--leading-d2":"1.2","--tracking-d2":"-0.015em","--text-d3":"clamp(2rem, 1.6rem + 2vw, 2.6875rem)","--leading-d3":"1.15","--tracking-d3":"-0.02em","--text-d4":"clamp(2.375rem, 1.6rem + 3.9vw, 3.5625rem)","--leading-d4":"1.1","--tracking-d4":"-0.025em","--tracking-label":"0.08em","--weight-display":"400","--font-display":"var(--font-circuit-display), ui-sans-serif, system-ui, sans-serif","--font-text":"var(--font-circuit-text), ui-sans-serif, system-ui, sans-serif","--font-sans":"var(--font-text)","--font-mono":"var(--font-circuit-mono), ui-monospace, 'Courier New', monospace"},"compatibility":{"next":">=15 <17","react":">=19 <20","tailwind":">=4 <5"},"dependencies":["lucide-react"],"editions":{"react":{"source":"src","runtime":"react"},"html":{"source":"html/src","output":"html/dist","engine":"nunjucks","runtime":"vanilla","buildRequired":false}},"ui_library":{"version":"1.4.0","files":["html/src/js/_tt/accordion-disclosure.js","html/src/js/_tt/anchor.js","html/src/js/_tt/dialog.js","html/src/js/_tt/field-ids.js","html/src/js/_tt/field.js","html/src/js/_tt/filter-chip.js","html/src/js/_tt/focusables.js","html/src/js/_tt/form-error-summary.js","html/src/js/_tt/layer.js","html/src/js/_tt/presence.js","html/src/js/_tt/reduced-motion.js","html/src/js/_tt/roving.js","html/src/js/_tt/tabs.js","html/src/js/_tt/tooltip.js","html/src/js/_tt/variant-selector.js","src/components/ui/_tt/accordion-disclosure.axes.ts","src/components/ui/_tt/accordion-disclosure.fixtures.ts","src/components/ui/_tt/accordion-disclosure.tsx","src/components/ui/_tt/anchor.ts","src/components/ui/_tt/capture.ts","src/components/ui/_tt/dialog.axes.ts","src/components/ui/_tt/dialog.fixtures.ts","src/components/ui/_tt/dialog.tsx","src/components/ui/_tt/field-ids.ts","src/components/ui/_tt/field.axes.ts","src/components/ui/_tt/field.capture.ts","src/components/ui/_tt/field.fixtures.ts","src/components/ui/_tt/field.tsx","src/components/ui/_tt/filter-chip.axes.ts","src/components/ui/_tt/filter-chip.fixtures.ts","src/components/ui/_tt/filter-chip.tsx","src/components/ui/_tt/focusables.ts","src/components/ui/_tt/form-error-summary.axes.ts","src/components/ui/_tt/form-error-summary.fixtures.ts","src/components/ui/_tt/form-error-summary.tsx","src/components/ui/_tt/form.axes.ts","src/components/ui/_tt/form.fixtures.ts","src/components/ui/_tt/form.part.tsx","src/components/ui/_tt/form.ts","src/components/ui/_tt/host.ts","src/components/ui/_tt/ids.ts","src/components/ui/_tt/layer.ts","src/components/ui/_tt/layout-effect.ts","src/components/ui/_tt/presence.ts","src/components/ui/_tt/recipe.ts","src/components/ui/_tt/reduced-motion.ts","src/components/ui/_tt/roving.ts","src/components/ui/_tt/tabs.axes.ts","src/components/ui/_tt/tabs.fixtures.ts","src/components/ui/_tt/tabs.tsx","src/components/ui/_tt/tooltip.axes.ts","src/components/ui/_tt/tooltip.fixtures.ts","src/components/ui/_tt/tooltip.tsx","src/components/ui/_tt/variant-selector.axes.ts","src/components/ui/_tt/variant-selector.capture.ts","src/components/ui/_tt/variant-selector.fixtures.ts","src/components/ui/_tt/variant-selector.tsx"]},"license":"standard","design":{"typefaces":{"display":"Barlow Condensed","text":"Hanken Grotesk","mono":"Space Mono"},"typeRatio":1.333,"signature":"The roll sheet: every class is a fixed number of ruled lines, set by the room's own hard integer capacity, filled top to bottom in booking order. A dashed rule crosses the sheet at the session's own start time — names above it carry an arrival stamp and a checkmark, names below it carry only the stamp. rollFor() computes every line and throws at build time on an oversold session, a membership tier booked into a room it cannot access, or a coach or room double-booked anywhere in the week. It runs on /, /schedule, and /class at three escalating renderings — a count, a strip, and the full sheet.","undertone":"a converted tram depot at 6am, ink-navy on a near-black room","heroArchetype":"A1"}}