Skip to content

Make home, /teams and 404 lighter without changing what they show - #118

Merged
willwashburn merged 2 commits into
mainfrom
claude/homepage-performance-optimization-7f2b16
Sep 23, 2026
Merged

willwashburn merged 2 commits into
mainfrom
claude/homepage-performance-optimization-7f2b16

Conversation

@barryollama

@barryollama barryollama commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

What changed

Performance and cleanup for the homepage, /teams and the 404 page. There are no copy or visual changes: the built HTML of all three pages matches main apart from the intended image attributes and sources, and the 404 output is identical.

  • Server-rendered brand icons. @lobehub/icons modules are all 'use client', and each default export attaches Avatar/Combine variants that pull in emoji data. That shipped about 145 KB of JS to every page just to draw a few logos. components/brand-icons.tsx renders the same SVG on the server; lib/test/brand-icons.test.tsx asserts the markup is identical to lobehub's, including gradient ids.
  • 404 backdrop loaded lazily. The root not-found boundary is part of every route's tree, so the drifting-terminal code was in every page's bundle. app/not-found/LostFieldLazy.tsx wraps it in next/dynamic: it still server-renders on a real 404, but its chunk only downloads there. Server-rendering it instead was tried and rejected, because Next serializes the root not-found tree into every page's RSC payload, which added about 220 KB of HTML per page.
  • Investor logos no longer pop in. They were loading="lazy" in the hero, and the WebP also went through /_next/image. They now load eagerly and unoptimized.
  • Display-sized images on /teams. Production has no Cloudflare IMAGES binding, so OpenNext's /_next/image returns the original file: 24px avatars were downloading 150–800 KB PNGs. scripts/generate-web-images.mjs writes 128px WebP avatars and q90 WebP screenshots, which look the same when zoomed. /teams image weight in and below the hero drops from about 4.7 MB to about 225 KB.
  • Offscreen animations pause. The search, event-feed, delivery-timeline and workflow-trace previews stop their timers while scrolled away and resume where they left off (components/useOnScreen.ts). The chat preview's 250 ms visibility poll and scroll listeners are replaced by one IntersectionObserver with the same trigger band.
  • Smaller bundles. The docs star badge moved to DocsGitHubStarsBadgeServer.tsx, so pages showing only the plain badge no longer bundle its client component and the docs nav.
  • Dead code removed. About 42 KB of unused CSS-module rules are gone from landing, flows, teams-landing, site-nav and enterprise. A check confirmed every remaining rule is unchanged and in the same order. The unused AgentSetupPrompt component is removed too.

Numbers

Per-page download compared with main: brotli-compressed HTML + JS + CSS, excluding the noModule polyfills; the build had a PostHog key set, as in prod.

Page Before After
Home 316 KB 272 KB (−14%)
/teams 304 KB 281 KB (−8%)
404 287 KB 243 KB (−16%)

Reviewer notes

  • One small behaviour difference: when you reach a 404 via in-app navigation, the drifting terminals appear a moment after the page, while their chunk loads. Loading a missing URL directly is unchanged.
  • Verified: tsc clean and the production build passes. In the browser I checked that the animations pause and resume, the chat preview starts on scroll, and the 404 terminals and click bursts work. lib/test/flow-push-guard.test.ts times out under the full parallel vitest run; it's an existing issue in untouched code and passes 18/18 on its own.
  • Out of scope, possible follow-ups: PostHog is now the largest remaining JS on every page (about 67 KB gzipped) and could start after the page is interactive, but that changes analytics timing. Adding a Cloudflare IMAGES binding would fix image sizing site-wide, but it's an infra change behind the cmo gate.

🤖 Generated with Claude Code


Note

Low Risk
Marketing-site performance and dead-code removal; one minor UX note is 404 terminals appearing slightly later on client-side navigation while the lazy chunk loads.

Overview
Performance-focused cleanup for the homepage, /teams, and 404: smaller downloads and less main-thread work, with no intended visual or copy changes.

Bundle and hydration: Marketing logos move from @lobehub/icons (client-only, ~145 KB) to server-rendered brand-icons.tsx with parity tests. The 404 LostField backdrop is next/dynamic so its chunk is not on every route. Docs star badge logic is split into DocsGitHubStarsBadgeServer.tsx so non-docs pages avoid the docs nav client bundle.

Runtime: Landing previews (search typing, realtime feed, delivery timeline, workflow trace) gate timers on useOnScreen so they pause off-screen and resume in place. ChannelMessagesPreview drops scroll polling for a single IntersectionObserver.

Assets: Investor logos load eager/unoptimized; hero avatars and team screenshots use generated WebP (generate-web-images.mjs) with unoptimized where /_next/image would serve full originals. Author/contact images point at -128.webp variants.

Removal: Unused CSS across landing/flows/teams/nav/enterprise modules, unused AgentSetupPrompt and related styles, and split of GitHubStars docs export.

Reviewed by Cursor Bugbot for commit 99d173a. Bugbot is set up for automated code reviews on this repo. Configure here.

- Render the lobehub marks these pages use from server-safe copies
  (components/brand-icons.tsx). Every @lobehub/icons module is 'use client'
  and its default export pulls in emoji data, ~145 KB of JS per page. A
  parity test checks the markup matches lobehub exactly.
- Lazy-load the 404 backdrop through a next/dynamic client wrapper. The root
  not-found boundary is part of every route, so its terminal code was in
  every page's bundle; it still server-renders on a real 404.
- Load the hero investor logos eagerly and unoptimized so they no longer pop
  in after layout.
- Serve display-sized WebP copies of the /teams avatars and concept
  screenshots (scripts/generate-web-images.mjs). Production has no Cloudflare
  IMAGES binding, so /_next/image returned the 150-800 KB originals.
- Pause the timer-driven previews while offscreen (useOnScreen) and replace
  the chat preview's 250 ms visibility poll with an IntersectionObserver.
- Move the docs star badge into its own module so pages with the plain badge
  don't bundle its client component and the docs nav.
- Remove unused CSS-module rules from landing, flows, teams-landing, site-nav
  and enterprise styles, and the unused AgentSetupPrompt component.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: c1d6b7e8-a870-4165-b677-9dddfce5daed


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Preview deployed!

Environment URL
Web https://7afd38d6-agentrelay-web.agent-workforce.workers.dev

This is a Cloudflare Workers preview version of this PR's build.

The inline Yonder SVG had only a viewBox, so it took its size (and green
colour) entirely from investor-strip.module.css. When a client navigation
to home painted before that stylesheet loaded (e.g. from the 404, which
doesn't carry it), the mark rendered at the full viewport width in white.
Give it the same 25px intrinsic size the stylesheet applies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@willwashburn
willwashburn merged commit c97bff3 into main Sep 23, 2026
5 checks passed
@willwashburn
willwashburn deleted the claude/homepage-performance-optimization-7f2b16 branch September 23, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants