Skip to content

Map: Execile landing page #1

Closed
18 of 18 issues completed
Closed

Description

@Abuubkar

Tracker: GitHub Issues. Tickets are sub-issues of this map; blocking uses native issue dependencies.

Destination

A build-ready spec plus implementation tickets for the Execile landing page: the design canvas ported to TanStack Start + StyleX + Vite+, statically prerendered, hosted on Cloudflare, with the Assessment Form delivered to the Google Workspace inbox through a Turnstile-protected Worker, and PostHog analytics. Done when nothing is left to decide before building. When the frontier empties, run /to-spec then /to-tickets against Decisions so far.

Notes

Domain. Marketing site for a medical billing / RCM service. Glossary in CONTEXT.md. Source of truth for structure and copy: Landing page ready for review/RCM Landing.dc.html. Sections: Hero, Problem, Services, How It Works, Specialties, Systems, Why Us, Fit, Results, FAQ, Assessment, Footer.

Audience. The developer plus agents. Tickets may prescribe and assume the rules below are known.

Skills each session should consult. frontend, codebase-design (base components are deep modules), domain-modeling, grilling; research for research tickets, prototype when behaviour is the question. Research findings live in docs/research/.

Stack. TanStack Start · TypeScript · SSG / static prerendering · Vite+ · StyleX · Cloudflare · Satoshi (Fontshare) · messages.json · Google Workspace (destination inbox for form submissions) · PostHog · Vite+ built-in lint/format and hook dispatcher (vp staged — Husky dropped, see issue #15).

Rules.

  1. No third-party animation libraries.
  2. Prefer CSS transitions/animations.
  3. Use Web APIs where appropriate.
  4. Respect prefers-reduced-motion.
  5. Animations must never block interaction.
  6. Animations must not cause layout shift.
  7. All user-facing text comes from messages.json.
  8. No raw base HTML elements in feature/page code.
  9. Base elements must be created as reusable base components, rendering semantic tags from day 1.
  10. Use the design system instead of arbitrary styling values.
  11. All public pages must be statically generated.
  12. No automated tests for v1.
  13. No internationalization. messages.json is a single English file.

Standing constraints.

  • No accounts exist yet (Cloudflare, domain, Google Workspace, PostHog). Nothing on this map may block on them; the spec must let the build run locally with a config/env layer that accepts credentials later.
  • Placeholders stay in the copy. The client updates the body at the end.
  • Spam protection on the form is Cloudflare Turnstile.
  • SEO is in scope but minimal: meta, one static OG image, sitemap, robots.
  • The StyleX research must also judge whether LightningCSS earns a place.

Decisions so far

Map complete. Frontier and fog are empty. The spec synthesising these decisions is #20 (ready-for-agent). Next: /to-tickets.

  • What is the performance budget, and what loads lazily? — measured, not estimated: ~143 kB critical path, of which 86 kB is TanStack Start's client runtime with no available lever (deferred hydration measurably makes it larger; hydrate: false is unmerged PR #6092) and 43 kB is Satoshi, unsubsettable by licence. posthog-js-lite would save ~75 kB but lacks cookieless_mode, so What does PostHog track, and how is it initialised? #13's no-banner posture forces the full build — loaded on idle. Turnstile defers to first form interaction. LCP is the hero h1, text-only. Documented target, no CI gate.
  • Skip link and table responsiveness: the accessibility decisions left after semantics — the Why Us comparison table stacks below a new 600px screen.table breakpoint rather than scrolling horizontally, because the canvas's overflow-x hides the Execile column and leaves only the competitor's visible on a phone; SkipLink is a new base component (not VisuallyHidden + Link, which is unconditionally hidden), with tabindex="-1" on main so focus actually moves. Container queries rejected while StyleX's @container ordering bug is open.
  • Problem section: sourced industry statistics and how citations render — the four placeholder stats replaced with attributed industry figures (MGMA 60%, MGMA 13.5% past 120 days, CAQH 25 min, 13 wks from BCBSTX + Ohio Rev. Code 3963.06 + La. R.S. 22:1009), each with a visible plain-text source line; "appeal windows quietly close" removed as unmeasured and replaced by the 120-day Medicare appeal rule; card 3 carries no percentage because none exists. Five widely-quoted figures were traced and rejected as unsourced. Amends ADR 0001: the canvas is source of truth for structure only.
  • How is the site deployed, and what is the provisioning checklist? — one Worker with Static Assets, wrangler versions upload on PRs and wrangler deploy on main from GitHub Actions; an 11-step provisioning checklist ordered by dependency, each step naming the variable it fills; Email Routing goes on a forms. subdomain so the apex MX stays with Google; everything but DNS, real delivery, real Turnstile and analytics ingestion is verifiable locally with no account.
  • What is the project scaffold, and what runs on commit? — vp create @tanstack/start + vp migrate; StyleX unplugin first in the plugin list; base/ exempt from lint, sections/+routes/ scoped to react/forbid-elements and react/jsx-no-literals (both native — the two unverified facts are resolved); the other four gaps are documented conventions in CLAUDE.md, no custom plugins; Husky dropped for vp staged; pre-commit is format+lint only, full checks in GitHub Actions with the placeholder check reporting on PRs and gating only production deploys; no baseUrl, or tsgolint silently skips type-checking.
  • What SEO and sharing metadata ships, and how is it generated? — head tags from m.meta on the root route, one hand-made 1200×630 og.png, hand-written robots.txt/sitemap.xml written at provisioning since they hard-code the domain; Organization JSON-LD, not LocalBusiness, because the registered address is a residence and only NY/US is published; brand is Execile, legalName is EXECIL PVT LTD; v1 ships indexable with pnpm placeholders as a hard pre-deploy gate.
  • What does PostHog track, and how is it initialised? — autocapture off, diverging from the research because Which base components exist, and what is each one's interface? #9 and How is each interaction built with native CSS and Web APIs only? #10 already enumerated every interactive element; 10 explicit events, none carrying a field value, with faq_opened keyed on a stable slug rather than an index; email_fallback_used and assessment_failed{reason} exist to audit What is the Assessment Form pipeline end to end? #12's recovery path and Email Service's Beta risk; cookieless with no banner and no BAA; no proxy in v1, so adblockers cause a systematic undercount that no later proxy backfills.
  • What is the Assessment Form pipeline end to end? — POST /api/assessment TanStack server route taking FormData, invisible Turnstile verified server-side, honeypot, server-side revalidation of a canvas-matching field set, env.EMAIL.send with replyTo the visitor; a delivery failure shows a role="alert" panel offering Open Email (mailto:) and Copy Message (clipboard) so the lead is recoverable manually; rate limiting is WAF config, not code; runs end to end locally on Turnstile test keys with a simulated email binding.
  • What is the shape of messages.json, and how is rule 7 enforced? — one file nested by section to mirror src/sections/, ~200 strings, list content as arrays of objects; the hero heading is the only rich text and uses a Segment[] encoding; static import via resolveJsonModule with no codegen; the canvas bracket convention is kept and a pnpm placeholders script lists what remains; react/jsx-no-literals everywhere, with attribute strings as a known blind spot.
  • Which base components exist, and what is each one's interface? — 26 components in three tiers; rule 9 read as "every tag is owned by exactly one base component" rather than one component per tag. Box/Text are deliberately shallow primitives with a closed as union; Button has no as (a button-styled link is Link variant="button"). Tokens reach components only through variant props, and style is for parent layout, never interior restyling. Layout is base/ ← sections/ ← routes/, no features/.
  • How is each interaction built with native CSS and Web APIs only? — native-first: declarative Popover API for the mobile menu, <details name="faq"> for the exclusive accordion with ::details-content animation, @media (hover:hover) guard, :focus-visible; the form submit is the only JavaScript on the page, and it is JS-only because Turnstile needs JS. No /thanks route — success is an inline role="status" swap. Prototype on branch prototype/interactions.
  • Which design tokens does the canvas define, and how do they become the StyleX design system? — ~110 canvas values normalised to 62 tokens in 9 groups under a frequency rule (ADR 0001); one defineVars group per category with ramp keys and derived role keys together, because a two-file palette→semantic split silently breaks subtree theming; the two dark blocks are a createTheme; contrast testing forced the CTA and link colour from teal600 to teal700 with a new teal800 hover.
  • How does StyleX compile inside TanStack Start on Vite, and is LightningCSS worth adding? — @stylexjs/unplugin 0.19.0 first in the plugin list, CSS via a side-effect import in the root route; LightningCSS is already inside Vite 8 and the unplugin, so only a browserslist field and lightningcssOptions.minify are wired; base components must accept a style prop and spread stylex.props() themselves.
  • Can Satoshi be self-hosted, and how is it loaded without layout shift? — Yes, the ITF licence recommends self-hosting but forbids subsetting; ship the unmodified variable WOFF2 with font-display: swap, a preload, and a metric-matched Arial fallback computed from the font file at build; @font-face lives in the plain CSS entry, not StyleX.
  • How should PostHog run on a static marketing site without a consent banner? — PostHog Cloud US in cookieless always mode with person profiles off, replay off, autocapture limited to link and button clicks, ph-no-capture on the form; npm package initialised client-only with an env token that no-ops when empty; no proxy and no BAA for v1.
  • How does a Cloudflare Worker deliver a form submission to a Google Workspace inbox? — Cloudflare Email Service send_email binding to the Workspace mailbox as a verified destination (free on every plan), sending from an Email Routing subdomain so Google's apex MX stays; wrangler dev simulates the binding locally; Resend is the runner-up.
  • What does Vite+ provide, and how does a TanStack Start project live inside it? — vp v0.3.0 beta bundles Vite 8, Oxlint, Oxfmt, tsgolint and pnpm; scaffold with vp create @tanstack/start then vp migrate; rules 7 and 8 map to react/jsx-no-literals and react/forbid-elements; Husky conflicts with Vite+'s hook dispatcher, decision parked in the scaffold ticket.
  • How does a statically prerendered TanStack Start site deploy to Cloudflare with one server endpoint? — One Worker with Static Assets via @cloudflare/vite-plugin; prerendered pages served as assets, the form POST as a TanStack server route in the same app; vite dev and Turnstile dummy keys run everything before any account exists.

Not yet specified

Empty. Every patch graduated into a ticket once its dependencies resolved — structured data into #14, the domain and email-domain setup into #16, accessibility into #17, and the performance budget into #18.

Out of scope

  • Legal pages (HIPAA Notice, Privacy, Terms). Footer links stay dead in v1; decided at the end.
  • Real copy and placeholder values. The client fills them after the build.
  • The build itself. This map ends at a spec and tickets.
  • Automated tests (rule 12) and internationalization (rule 13).

Activity

  1. Abuubkar commented on Sep 6, 2026

    @Abuubkar
    OwnerAuthor

    The map is finished. All 18 decision tickets are resolved and closed, the spec they fed (#20) is closed, and every implementation ticket derived from it is merged.

    Remaining work needs accounts, signatures or human decisions rather than wayfinding, so it moves to #34: provisioning steps 1 and 3 to 10, legal review of the three new legal pages, and the competitor-review items that were deliberately deferred.

    Research findings stay in docs/research/, ADRs in docs/adr/, and the glossary in CONTEXT.md.

  2. added a commit that references this issue on Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wayfinder:mapWayfinder map (index of decisions)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions