Skip to content

Instantly share code, notes, and snippets.

@shakyShane
Last active June 9, 2026 07:37
Show Gist options
  • Select an option

  • Save shakyShane/aab408f0552fe7d692970ef4ee64a060 to your computer and use it in GitHub Desktop.

Select an option

Save shakyShane/aab408f0552fe7d692970ef4ee64a060 to your computer and use it in GitHub Desktop.
Mobile homepage below-the-fold port plan (static-pages → home-mobile)

Below-the-Fold Port Plan (v3)

Target: apps/home-mobile async chunk → @staticpages/turbo-shared/btf
Source: static-pages rebrand only (home-rebrand/, rebrand/, pages/app/)
Future: apps/home-desktop imports the same export
Gist: https://gist.github.com/shakyShane/aab408f0552fe7d692970ef4ee64a060


What we're actually building

Not a page architecture. One deliverable:

// home-mobile (today) and home-desktop (later)
import { BelowTheFold } from "@staticpages/turbo-shared/btf";

// inside existing dynamic(..., { ssr: false }) boundary:
<BelowTheFold variant="in-app" />;

Everything else is staging work to get there.


Where it lives

packages/turbo-shared/src/btf/          ← new folder, sibling to components/, hooks/, utils/
  index.tsx                             ← Stage 2: sole public export
  below-the-fold.tsx                    ← wrapper component (origin, legacy hide, shell)
  in-app/                               ← mobile homepage variant (from home-rebrand)
  promotional/                          ← desktop promotional variant (future, not stage 1)
  app-page/                             ← extracted AppRebrand (from pages/[locale]/app)
  sections/                             ← download-options, product-showcase, compare table, FAQ, footer…
  adapters/                             ← bridge static-pages hooks → turbo-shared providers
  assets/                               ← favorite icons etc.

Add to packages/turbo-shared/package.json exports:

"./btf": "./src/btf/index.tsx"

turbo-shared is already the shared delivery point for turbo apps. BTF belongs here — not a new package, not copies in home-mobile/src.


Rebrand scope (unchanged)

Use Path
home-rebrand/in-app-home-below-the-fold.tsx and friends
rebrand/product-showcase, rebrand/faq-section, rebrand/footer, etc.
pages/[locale]/app/index.tsx (component only — strip page exports)
components/pages/home/ legacy tree

Import-graph from rebrand BTF roots: ~122 TS files (+ SCSS + PNG assets). Breakdown:

Bucket ~Files Stage 1 action
icons/ 45 Copy into btf/icons/ or symlink; icons are leaf deps
rebrand/ + pages/app/ + components/pages/app/ ~30 Core section components
utils/ + hooks/ ~28 Don't copy — wire to btf/adapters/ → existing turbo-shared
stores/ + misc ~19 Copy or stub (atbStore only needed for app-page campaign id)

Two-stage path

Stage 1 — Dump, wire, look

Goal: Get real rebrand BTF rendering in home-mobile's async chunk. Accept messy internals. Learn what's missing.

Do not polish folder structure or API yet. Do get visual parity with static-pages /home/mobile scrolled to BTF.

1a. Scaffold turbo-shared/src/btf/

  • Create folder + minimal index.tsx re-exporting a work-in-progress component
  • Add turbo-shared deps: @staticpages/design-system, motion, classnames (already have), possibly @reach/visually-hidden
  • Add jest/webpack/svg handling if icons need it (mirror home-mobile's next config patterns for turbo-shared consumers)

1b. Mechanical file dump (one PR, one sitting)

Copy rebrand BTF subtree from static-pages into btf/ preserving relative structure enough to compile. Suggested copy order (all in one branch — order only matters for incremental debugging if build breaks):

  1. in-app-home-below-the-fold.tsx + .module.scss + assets/icon*.png
  2. download-options.tsx + scss
  3. product-showcase.tsx + chip + scss
  4. app-page/ — extract App default export from pages/[locale]/app/index.tsx; copy components/pages/app/*
  5. Follow broken imports — pull in rebrand/compare-privacy-table, rebrand/download-panel, rebrand/faq-section, rebrand/footer, rebrand/addToBrowser/, etc.

1c. Bulk import rewiring (search-replace + adapters)

Inside btf/ only, replace static-pages aliases:

Was Becomes
@hooks useDevice btf/adapters/use-device.ts → re-export turbo-shared DeviceProvider hook
@hooks useOrigin extend turbo-shared/utils/origin (add content segment + decorateOriginInUrl)
@utils/pixel Pixel turbo-shared/utils/pixel
@components/themedImage copy small component into btf/ or turbo-shared/components/
@icons/* btf/icons/ copies or shared icons package later
@pages/[locale]/app btf/app-page/app-rebrand.tsx

Leave // @intl-meta pragmas — they'll get picked up when home-mobile runs i18n:messages.

1d. home-mobile — swap placeholder for turbo-shared import

// page.tsx — keep existing dynamic boundary, change target only
const MobileBelowTheFoldIsland = dynamic(
  () => import("@staticpages/turbo-shared/btf").then((m) => m.BelowTheFold),
  { ssr: false, loading: () => null },
);

// page.tsx render — thin shell stays in app
<MobileBelowTheFoldIsland
  variant="in-app"
  id={HOME_MOBILE_BELOW_THE_FOLD_ID}
  testId="below-the-fold"
/>;

Stage 1 BelowTheFold can be a thin rename of ported InAppHomeBelowTheFold + wrapper styles. Props minimal: variant, id, testId.

1e. Expand i18n + verify

  • home-mobile #i18n:messages: add app, add-to-browser, compare-privacy, compare-privacy-compact, homepage-faq
  • Run npm run i18n:extract from root after porting strings
  • turbo run dev --filter=home-mobile → scroll pull-tab → compare against static-pages mobile

Stage 1 exit criteria

  • BTF visually matches static-pages rebrand mobile (top heading, download options, chips, compare table, feature cards, FAQ, footer)
  • BTF CTAs have origin=…__details
  • No SCSS leaked into ATF inline CSS bucket (monolithic dynamic import preserved)
  • Build + types pass

Stage 1 explicitly defers: clean internal folder layout, static-pages dedup, home-desktop, promotional variant, exhaustive tests.


Stage 2 — Single export, stable contract

Goal: BelowTheFold is the only import surface. Internals reorganized. Desktop-ready.

Public API (frozen)

// packages/turbo-shared/src/btf/index.tsx
export { BelowTheFold } from "./below-the-fold";
export type { BelowTheFoldProps, BelowTheFoldVariant } from "./below-the-fold";

type BelowTheFoldVariant = "in-app" | "promotional";

type BelowTheFoldProps = {
  /** Mobile homepage uses "in-app". Desktop promotional will use "promotional". */
  variant?: BelowTheFoldVariant;
  /** Scroll target for pull-tab. Mobile: "home-below-the-fold". Desktop may use "features". */
  id?: string;
  testId?: string;
  /** Origin content segment. Default "details" → funnel_home_website__details */
  originContent?: string;
  className?: string;
};

Internal routing (not exported)

function BelowTheFold({ variant = "in-app", ...shell }: BelowTheFoldProps) {
  return (
    <BelowTheFoldShell {...shell}>
      <OriginCustomizer content={shell.originContent ?? "details"}>
        {variant === "in-app" ? <InAppContent /> : <PromotionalContent />}
      </OriginCustomizer>
    </BelowTheFoldShell>
  );
}
  • InAppContent = current InAppHomeBelowTheFold body
  • PromotionalContent = port promotional-home-below-the-fold.tsx when home-desktop needs it (Stage 2b)

Shell responsibilities (shared mobile + desktop)

Lives in below-the-fold.tsx, not in each app:

  • id / data-testid on outer <section>
  • .belowTheFoldWrapper styles (from rebrand minimal-homepage.module.scss)
  • OriginCustomizerProvider (content=details)
  • Hide on .is-legacy-device
  • DS motif side-effect imports (mandarin, lilypad, pollen, pondwater)

Apps become trivial:

// home-mobile
<BelowTheFold variant="in-app" id="home-below-the-fold" testId="below-the-fold" />

// home-desktop (future)
<BelowTheFold variant="promotional" id="features" testId="belowTheFold" />

Stage 2 cleanup

  • Reorganize dumped files into sections/, app-page/, in-app/, promotional/
  • Delete duplicate adapters; consolidate origin/pixel into turbo-shared proper
  • Add turbo-shared unit tests for BelowTheFold shell (origin decoration, legacy hide)
  • Add home-mobile integration tests (assertBelowTheFold origin pattern)
  • Optional: rewire static-pages home-rebrand/in-app-home-below-the-fold to import from @staticpages/turbo-shared/btf

Stage 2 exit criteria

  • Only @staticpages/turbo-shared/btf imported by turbo apps for BTF
  • BelowTheFoldProps documented and stable
  • promotional variant implemented or stubbed with clear TODO for home-desktop
  • Tests for origin + visibility

Why two stages (not big-bang architecture first)

Approach Risk
Design perfect package API first, then port Spend days on structure before knowing what breaks (icons, origin, i18n subset, motion, atbStore, app redirect hooks)
Dump → look → contract Stage 1 surfaces real integration gaps in 2–3 days; Stage 2 codifies what actually worked

Stage 1 is deliberately allowed to be ugly inside btf/. The async chunk boundary in home-mobile already isolates it from ATF perf concerns.


home-mobile wiring (unchanged invariant)

page.tsx (sync)
  HeroLayout + ATF components
  dynamic(() => import('@staticpages/turbo-shared/btf'))  ← async chunk
    BelowTheFold
      … all BTF SCSS + DS + motion …

Never import BTF modules synchronously in page.tsx. Never split BTF into multiple top-level dynamic imports unless each is SCSS-safe.


Realistic effort

Stage Work Time
1a Scaffold + deps turbo-shared btf/ folder, package.json exports + deps 0.5 day
1b–c Dump + rewire Copy ~122 files, adapter pass, fix build 2–3 days
1d–e Wire + visual check home-mobile import swap, i18n, side-by-side 1 day
Stage 1 total ~3–4 days
2 API + cleanup + tests + promotional stub ~2–3 days
Grand total ~5–7 days

Decisions locked

Decision Choice
Package location packages/turbo-shared/src/btf/
Public export @staticpages/turbo-shared/btfBelowTheFold
Design Rebrand only
Stage 1 variant in-app only
Legacy pages/home/ Out of scope
Separate @staticpages/home-btf package No — use turbo-shared

File copy roots (Stage 1 starting points)

Run import-graph walk from these four files only:

  1. apps/static-pages/src/components/pages/home-rebrand/in-app-home-below-the-fold.tsx
  2. apps/static-pages/src/components/pages/home-rebrand/download-options.tsx
  3. apps/static-pages/src/components/rebrand/product-showcase.tsx
  4. apps/static-pages/src/pages/[locale]/app/index.tsx

Stop at any path under components/pages/home/.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment