Minisites
Per-organization marketing sites rendered by Astro at the org’s custom host (apps/minisites). Distinct from Taikan’s own marketing site (apps/marketing); both share the Astro stack but the minisites app is multi-tenant and dynamic.
What
Each Taikan organization can publish a multi-page site that combines:
- Owner-authored content (hero copy, about-us, gallery, testimonials, FAQ, social, contact).
- Live platform data fetched from the Taikan API at request time (
programs,upcomingSessions,plans,courses,coaches,events).
The site resolves itself from the incoming Host header against the minisite_content table, either a custom domain (fit.gymname.com) or a *.taikan.fit subdomain. Since FIT-209 the renderer is multi-page: a fixed page set (Home, plus owner-toggleable Courses, Workshops, About, Contact) routed by URL slug.
Why
- Gym owners can publish a public site without leaving the Taikan dashboard or buying a separate Squarespace plan.
- Live data (class schedule, plans, courses) stays in sync automatically — no double-entry between Taikan and a separate CMS.
- Astro keeps each page <100KB and CDN-cacheable.
Who
- Gym owners edit content via the Taikan dashboard minisite editor; publishing flips the
is_publishedflag and snapshotscontent→published_content. - Prospective members land on the minisite from search, social, or QR codes — see schedule, pricing, and submit a contact form that lands as a lead.
Persona impact
| Persona | Impact |
|---|---|
| Gym owner | Owns their public web presence inside Taikan, no third-party site needed. |
| Coach | Surfaced on the trainers section; their availability + program affiliation shows automatically. |
| Prospect | Discovers a gym’s offering and books an intro through the contact form (lead → CRM). |
Capabilities
- Multi-tenant resolution from
Hostheader, eithercustom_domainorsubdomain. - Multi-page composition: a fixed page set (Home always-on, plus owner-toggleable Courses, Workshops, About, Contact). Each page is slug-routed and carries its own ordered section list.
- Section composition per page: hero, about, classes, schedule, pricing, courses, trainers, contact, gallery, testimonials, faq, social, events. Each toggled per-org and per-page.
- Social section: manual Instagram / TikTok / Facebook / YouTube links plus curated post thumbnails.
- Events / workshops: dated, promotable entries authored in the editor and surfaced via the new
minisite_eventstable (lead-capture, not purchasable). - Timed lead-capture popup: fires after a delay or on exit intent, posts name + phone as a lead.
- Pricing section (FIT-287): server-gated intro pricing terms and effective seat availability on plan cards, plus an optional purchase CTA that links a plan card straight into the public join chain instead of the contact form. Both are double/triple-gated (PostHog flags + per-site editor opt-in) — a site that hasn’t opted in renders byte-identical to before. See behavior.md.
- Theme controls: primary / secondary colors, body + heading font families, button style, corner style, section density, favicon, SEO title/description. Default template is a warm copper editorial look;
headingFontFamily,cornerStyle, andsectionDensityare wired into the layout as of the FIT-287 design rework (previously stored/editable but ignored by the renderer). - Draft / publish workflow:
contentis the working draft,published_contentis the live snapshot. - Locale-aware (
he/en/ru), defaults to the org’s locale and falls back to Hebrew. - Top nav switches to page links on multi-page sites and stays as in-page section anchors for single-page sites.
- Floating WhatsApp button when the contact section provides a number.
- Hero image preloaded via
<link rel="preload">to shorten LCP.
Related features
marketing-site— shares the Astro toolchain.webhooks— Clerk doesn’t gate minisite reads; they’re fully public.minisitesschema lives inlibs/db/src/lib/schema/minisites.ts.- API resolve endpoint:
GET /minisites/resolve?host=...(public). public-join-links(FIT-251) — the purchase CTA (FIT-287) links into this chain (/join/:token?plan=); it does not add a new checkout surface.plan-groups/ effective seat capacity (FIT-289) — the minisite reads the same binding plan-vs-group seat computation the dashboard plan cap enforcement uses, via shared helpers inapps/api/src/plans/plan-capacity.util.ts.
Status
Shipped. Editor lives in the dashboard. Minisite rendering app deploys independently to Vercel.
Gaps
- No A/B testing harness, every visitor sees
published_contentas-is. - No page-level analytics (PostHog page views only). Conversion funnel through the contact form lacks lifecycle attribution.
- The page set is fixed (Home, Courses, Workshops, About, Contact). Owners can enable/disable and reorder these but cannot author arbitrary new pages, and there is no blog / case-studies page type yet.
- Events are lead-capture only, not purchasable. There is no payment or entitlement coupling and no per-event RSVP/registration ledger.
- Event registration reuses the generic org lead capture (
source: 'minisite'), so a lead is not attributed to the specific event that drove it. - Theme tokens are still template-level, no per-section font overrides and no CSS variable escape hatch for power users.
- Custom domain SSL relies on Vercel’s automated provisioning; misconfigured CNAMEs surface a generic 404, not a setup hint.
- Purchase-mode “sold out” CTA is cosmetic: it routes to the same generic contact form as everything else, with no
campaignRef/prefill threading the lead as a waitlist signup for that specific plan. - Plan/seat edits do not bust the resolve cache (only publish/unpublish/domain/visibility/events do) — a sold-out plan can look open for up to ~5-6 minutes; true enforcement happens at purchase time in the subscription-insert transaction, so this is a staleness annoyance, not a correctness bug.
- External-payment-link orgs (plans with
paymentLinkUrl, mutually exclusive with intro/caps) cannot use purchase mode — thejoinUrlgate requires an active in-app payment config, so those orgs keep the lead-form CTA even withctaMode: 'purchase'selected. - No stats/highlights authoring exists yet for the About section or hero-adjacent dark bento cards — the design system has the
.card-darkprimitive but nothing populates it (owner-authored numbers only, never invented). - No screenshot-based visual QA pass has been run yet against the FIT-287 design rework (RTL,
cornerStyle/sectionDensityvariants, reduced-motion, no-JS) — see qa-plan.md.