fix(layout,splash): enforce global chrome across /lighthouse + overhaul first-visit splash logic#39
Open
devin-ai-integration[bot] wants to merge 9 commits into
Open
Conversation
…-visit splash - Move FirstVisitSplash mount from HomePage to root layout so it fires on the user's very first landing regardless of entry URL (fixes the 'only shows on the second visit to /' bug). - Gate the splash behind a micro-saas entry-point check: suppress on /tools* and on any utm/ref/source/utm_campaign value matching /micro[-_ ]?saas|microsaas/i. Bump storage key to v2 so existing visitors evaluate the new rules once. - Bring /lighthouse in line with the global marketing chrome: its layout no longer renders BrandHeader/BrandFooter/SiteContactDrawer directly. Instead the lighthouse audit and report-viewer pages wrap their content in MarketingChrome, which guarantees the same sticky header, mobile nav, gold trim, reach-out dialog, and BrandFooter as the rest of the site. - Extend MarketingChrome with optional headerCurrentSection / footerBuildTag / footerPoweredBy / segmentClassName props so the lighthouse surface can keep its 'audit' chip and Scanner v2 / Powered-by attribution inside the shared chrome. - /lighthouse/report/[id]/print stays intentionally outside MarketingChrome to keep the PDF output clean. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Deploying designedbyanthony with
|
| Latest commit: |
f6d1984
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://46f6e162.dba-92r.pages.dev |
| Branch Preview URL: | https://devin-1777566257-global-layo.dba-92r.pages.dev |
Merge origin/main into branch. Resolves conflicts in: - apps/web/src/app/layout.tsx (drop layout-shell.css import; combine font setup with global FirstVisitSplash mount) - apps/web/src/components/marketing/MarketingChrome.tsx (keep main's inline-Tailwind sticky-header chrome AND new optional props for segment customization on /lighthouse). Also bumps FirstVisitSplash to v3 storage key and reads window.location directly in useEffect instead of useSearchParams, eliminating the Suspense/hydration race that prevented the splash from firing on the user's true first paint. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
Mounting the splash globally in the root layout caused it to fire on the print sub-route, which is intentionally bare for clean PDF output. Skip without persisting the flag so normal subsequent visits still trigger the splash on first paint. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
…ite) group) Main moved /lighthouse and /lighthouse/report routes from apps/web/src/app/lighthouse/ into the (site) route group at apps/web/src/app/(site)/lighthouse/. Accept main's relocation and delete my old lighthouse/layout.tsx + lighthouse/page.tsx that were superseded by the (site)/lighthouse/page.tsx wrapper which already uses MarketingChrome. Splash v3 changes (drop useSearchParams + PRINT_PATH_PATTERN guard) remain intact on this branch. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
…e) move Phase 1A on main moved /lighthouse routes into the (site) route group but introduced two bugs that Devin Review flagged: 1. lighthouse-globals.css (~2000 LOC of audit UI styling) lost its only importer when apps/web/src/app/lighthouse/layout.tsx was deleted. The entire scanner UI was rendering unstyled. Add a new apps/web/src/app/(site)/lighthouse/layout.tsx that imports the relocated CSS and keeps LighthouseJsonLd / LighthouseTechFingerprints + segment metadata. 2. (site)/lighthouse/page.tsx wraps content in <MarketingChrome> which already renders <main id="main-content">, but the page then nested a second <main id="main-content"> inside it — duplicate landmark IDs, invalid HTML, broke screen-reader nav and Playwright #main-content selectors. Replace the nested <main> with a plain <div>. Also: - Re-attach the audit chip + Lighthouse Scanner v2 footer + Powered-by attributions via the optional MarketingChrome props introduced earlier in this PR. - Add segmentClassName="lighthouse-segment" so CSS rules scoped to .lighthouse-segment (~10 occurrences) actually apply. - Fix the relative @import paths in lighthouse-globals.css (now one directory deeper after the (site) move). - Update the biome.json override include path to match the new CSS location so the per-file lint exemptions still take effect. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
Devin Review noted the report MarketingChrome wrapper was missing `segmentClassName="lighthouse-segment"`, so the .lighthouse-segment scoped CSS rules (padding, layout, score-card overrides) wouldn't apply on the report viewer route — the main /lighthouse page got the prop in the previous commit but the report shell was missed. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
Devin Review noted my new (site)/lighthouse/layout.tsx exported only
title + description, dropping the canonical URL, openGraph block,
twitter cards, robots directives, keywords, category, viewport, and
appleWebApp config that the deleted apps/web/src/app/lighthouse/layout.tsx
had. Next merges parent metadata partially (title/description) but
fully replaces openGraph and twitter blocks, so leaving them out
silently broke OG image, OG URL, twitter:image, and the
`<link rel="canonical">` for /lighthouse.
Restore the full metadata + viewport export from the pre-Phase-1A
layout, including alternates.canonical pointing at absoluteSiteUrl("/lighthouse").
Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
Main shipped the next major refactor wave while this PR was open: - Phase 1B/2/3: AuditResults migration + deliverable bronze + CSS demolition - SEV-0: purge ghost classes from Lighthouse landing components - SEV-1: Linear/Stripe canonical glass + display weight downgrade - SEV-2: script orchestration, JSON-LD, global bronze sweep That demolished apps/web/src/app/(site)/lighthouse/lighthouse-globals.css and the segment layout I had added on this branch — main moved fully to design-system tokens (SECTION_SHELL, SURFACE_CARD_TECHNICAL, etc.) for lighthouse styling, so the per-segment CSS file and its layout importer are intentionally gone. Conflict resolution: - Accept main's deletion of (site)/lighthouse/layout.tsx and (site)/lighthouse/lighthouse-globals.css. - Accept main's rewritten (site)/lighthouse/page.tsx and (site)/lighthouse/report/[id]/page.tsx (canonical design-system tokens, no longer needs my old MarketingChrome props). - KEEP this branch's FirstVisitSplash.tsx (v3 logic that reads window.location directly on mount and skips /print) — main had reverted to the original v1 HomePage-only logic, but this PR's whole point is fixing the splash so we re-apply v3 over main. - Drop the now-stale biome.json override block that referenced the deleted lighthouse-globals.css. - Fix duplicate `btnPrimaryAudit` import in AuditForm.tsx that Git's auto-merge inserted. The MarketingChrome optional props from earlier in this PR (headerCurrentSection, footerBuildTag, footerPoweredBy, segmentClassName) are now unused but stay as harmless extension points; main's lighthouse pages just don't pass them. Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
Main shipped The Ledger feature suite and several other Phase-4 follow-ups while this PR was open: - D1 schema/admin app + Stripe webhook ledger pipeline - Turnstile site-key resolver pulled into AuditForm - Bespoke config messaging + EN/ES locale switcher + checkout success route Only one real content conflict: AuditForm.tsx imports — main added `resolveEffectiveSiteKey` from `@/lib/turnstile` next to the existing `buildPublicApiUrl` import. Took main's version (both imports kept). Splash v3 + global FirstVisitSplash mount in root layout survived the auto-merge intact (verified). Co-Authored-By: Anthony Jones <anthony@designedbyanthony.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related UX bugs, one PR.
1. Global layout chrome (incl.
/lighthouse)/lighthousewas renderingBrandHeader/BrandFooter/SiteContactDrawer/ a bespokeCookieConsentBannerdirectly in its ownlayout.tsx, which meant it diverged from the rest of the marketing site (no stickysite-chrome-stickywrapper, no mobile-nav overlay, a different cookie banner, different footer metadata surface, etc.).apps/web/src/app/lighthouse/layout.tsxis now a thin segment wrapper — metadata + fonts +LighthouseJsonLd+LighthouseTechFingerprintsonly.apps/web/src/app/lighthouse/page.tsxandapps/web/src/app/lighthouse/report/[id]/page.tsxwrap their content in the sharedMarketingChrome, so lighthouse now gets the exact same sticky brand header (with the gold trim rule), mobile-nav overlay, reach-out dialog, site-body-canvas,BrandFooter, cookie consent banner, and GTM/analytics scripts as(site)/*.MarketingChromegained four optional props so lighthouse can keep its "audit" chip in the header and its "Lighthouse Scanner v2 · Powered by Gemini / ElysiaJS / Next.js" attribution in the footer without forking the component:headerCurrentSection?: "audit"footerBuildTag?: stringfooterPoweredBy?: ReadonlyArray<{ label; href }>segmentClassName?: string/lighthouse/report/[id]/printis intentionally left outsideMarketingChromebecause the existing global@media printrules inlayout-shell.csshide.site-body-canvas— keeping PDF output clean.The gold trim (
.dba-header-rule) lives insideBrandHeaderand its CSS is already loaded globally viadba-global.css→brand-chrome.css, so consolidating every page ontoMarketingChromeis what actually makes the trim render consistently everywhere.2. First-visit splash popup (critical bug)
The splash was mounted inside
HomePage(apps/web/src/components/marketing/HomePage.tsx), so it only existed in the React tree when the user rendered/. A visitor who landed on/lighthouse,/services/*,/contact,/tools, etc. as their first URL never saw the splash; it only fired on their second visit (when they navigated to/).FirstVisitSplashis now mounted once in the root layout (apps/web/src/app/layout.tsx), wrapped in a<Suspense fallback={null}>becauseuseSearchParamsforces the subtree onto the client.<FirstVisitSplash />render fromHomePage.dba_first_visit_shown_v1→dba_first_visit_shown_v2so existing visitors get evaluated once under the new rules.localStorageaccess is wrapped in try/catch for private-mode / storage-disabled browsers.pathname === "/tools"orpathname.startsWith("/tools/"), orref,source,utm_source,utm_campaign,utm_medium,utm_contentsearch-param values match/micro[-_ ]?saas|microsaas/i.biome-ignoreforuseExhaustiveDependencies).Review & Testing Checklist for Human
/,/lighthouse,/contact,/services/local-seo, an arbitrary marketing slug like/services/custom-web-design./toolsfirst in a fresh incognito window → splash must not appear; then navigate to/→ splash must still not appear (micro-saas entry sticks for that visitor)./?utm_campaign=microsaas_launchfirst in a fresh incognito window → splash must not appear./lighthousepage side-by-side with/and/tools: same sticky header, same gold trim under the header, same footer, same reach-out sticky button, same cookie consent banner. The only intentional differences are the "audit" chip in the header and the "Powered by Gemini / ElysiaJS / Next.js" row in the footer./lighthouse/report/<id>— same chrome as above should render around the report, and the "Print / Save as PDF" CTA should still land on a clean/printpage with no marketing chrome.Notes
apps/web/src/components/JsonLd.tsxthat is unrelated to this PR (confirmed by runningbun run lintonmainbefore any of these changes).bun run typecheckandbun run buildboth pass locally against this branch.Link to Devin session: https://app.devin.ai/sessions/eb3d9c0a8a374727b60829b239ae5835
Requested by: @Designed-By-Anthony