Stripe's compliance crawler fetches the apex URL without executing JS and
declined live-mode review when `https://resolutionflow.com/` returned the
empty SPA shell that redirected to /landing client-side. Restructure the
router so / serves LandingPage directly:
- `/` → new `PublicLanding` wrapper (LandingPage for anon; Navigate to
/home for authed users so there's no marketing-frame flicker).
- Authed tree converted to a path-less layout route with absolute child
paths. QuickStartPage moves to `/home`; all other children
(`/trees`, `/pilot`, `/admin/*`, `/account/*`, etc.) keep their URLs.
- `/landing` kept as a one-release stale-bookmark redirect to /.
- `ProtectedRoute` unauth redirect flipped /landing → /; `state.from`
preserved for post-login return.
Reference updates:
- Post-login / post-onboarding destinations → /home: OAuthCallbackPage
(incl. `?welcome=teammate` query), WelcomeStep1/2/3 dismiss-rest,
AssistantChatPage post-escalate, WelcomeRouter completion/dismiss
redirects, VerifyEmailPage's three "Go to dashboard" links.
- Authed chrome → /home: TopBar logo, AppLayout mobile nav + drawer
logo, CommandPalette Dashboard entry.
- Dashboard onboarding → /home: NextStepCard `ran_session.ctaPath`,
SetupChecklist `ran_session.path`, SessionHistoryPage empty-state CTA.
- Public back-links → /: TermsPage, PrivacyPage, PoliciesPage,
ContactPage, PromotionsPage, PublicTemplatesPage (header + footer).
SharedSessionPage's `to="/"` left as-is — now correctly lands anon
visitors on the public landing.
Crawlability:
- New `frontend/public/robots.txt` allowlisting public pages and
disallowing the authed app.
- New `frontend/public/sitemap.xml` for /, /pricing, /contact-sales,
/contact, /templates, /terms, /privacy, /policies, /promotions.
- `PageMeta` gains an `og:url` (defaults to `window.location.href`) and
flips `twitter:card` to `summary_large_image` when an `ogImage` is
passed.
Tests:
- `AppLayout.test.tsx` updated to mount at `/home`.
- New `ProtectedRoute.test.tsx` asserts unauthenticated `/home`
redirects to `/` (not `/landing`) and preserves origin in `state.from`.
If Stripe's crawler still cannot see the site after this (zero-JS
crawler), the documented next escalation is server-side prerendering of
public routes via `vite-plugin-ssg`. Out of scope here.
Plan: docs/plans/2026-05-13-public-landing-routing-refactor.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Mechanical find-and-replace: rgba(249,115,22,...) → rgba(96,165,250,...)
across ~40 component and page files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace all rgba(6,182,212,...) cyan focus borders and accents with
rgba(249,115,22,...) ember orange across 21+ component files
- Remove all var(--glass-border) references (undefined variable) with
var(--color-border-default) across 24 files
- Remove deprecated blur orbs and glass-morphism effects from
SurveyPage, SurveyThankYouPage, and LoginPage
- Migrate landing.css from hardcoded hex to CSS custom properties
(~97 replacements for single-source theming)
- Fix off-palette grays in FlowPilotAnalyticsPage chart styling
(#8891a0 → #848b9b, #18191f → var(--color-bg-card))
- Update stale comments: "cyan brand" → "accent brand" in GlowEdge,
"gradient cyan square" → "gradient orange square" in BrandLogo
- Rename glow-cyan SVG filter ID to glow-accent
- Fix category color comment: "cyan" → "deep orange"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add types, API client, page component, card components, detail modal,
and /templates route for the public templates gallery. Uses raw fetch()
for unauthenticated access, glass-card design system, and URL-synced
filters with debounced search.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>