|
| 1 | +# Homepage, Library Landing, and Docs Performance Plan |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Make the homepage, library landing pages, and docs materially faster, lighter, and cheaper to render without regressing content quality or navigation UX. |
| 6 | + |
| 7 | +## Current Baseline |
| 8 | + |
| 9 | +- Homepage route chunk: `dist/client/assets/index-Bq0A5jmY.js` at `564.79 kB / 172.14 kB gzip` |
| 10 | +- Shared shell chunk: `dist/client/assets/app-shell-BikUtTEO.js` at `349.55 kB / 110.08 kB gzip` |
| 11 | +- Search modal chunk: `dist/client/assets/SearchModal-Bl-tUxqr.js` at `195.54 kB / 54.27 kB gzip` |
| 12 | +- Docs shell chunk: `dist/client/assets/DocsLayout-Bga1-HA9.js` at `17.61 kB / 6.05 kB gzip` |
| 13 | +- Markdown chrome chunk: `dist/client/assets/MarkdownContent-ia2V1dk8.js` at `19.37 kB / 6.39 kB gzip` |
| 14 | +- Global CSS: `dist/client/assets/app-CBMELhsb.css` at `319.24 kB / 40.48 kB gzip` |
| 15 | + |
| 16 | +## Main Problems |
| 17 | + |
| 18 | +- Homepage ships too much in one route chunk. |
| 19 | +- Library landing pages pay docs-shell and docs-config cost before the user asks for docs. |
| 20 | +- Docs still do too much work per request even with GitHub content caching. |
| 21 | +- Hidden docs UI still mounts and runs effects/queries. |
| 22 | +- Anonymous docs users still trigger auth-related client queries for framework preference. |
| 23 | +- Some "lazy" controls are effectively eager. |
| 24 | + |
| 25 | +## Success Targets |
| 26 | + |
| 27 | +- Cut the homepage route chunk hard enough that it is no longer one of the top client payloads. |
| 28 | +- Remove docs-config and docs-layout from the critical path for landing pages. |
| 29 | +- Turn docs page rendering into mostly cached work. |
| 30 | +- Avoid client queries on first paint for content that can be rendered server-side. |
| 31 | +- Reduce hidden-work JS on docs mobile and desktop layouts. |
| 32 | + |
| 33 | +## Workstreams |
| 34 | + |
| 35 | +### 1. Homepage route diet |
| 36 | + |
| 37 | +Targets: |
| 38 | + |
| 39 | +- `src/routes/index.tsx` |
| 40 | +- `src/components/OpenSourceStats.tsx` |
| 41 | +- `src/components/ShowcaseSection.tsx` |
| 42 | +- `src/components/PartnersGrid.tsx` |
| 43 | +- `src/components/MaintainerCard.tsx` |
| 44 | + |
| 45 | +Changes: |
| 46 | + |
| 47 | +- Break below-the-fold homepage sections into viewport-triggered lazy boundaries. |
| 48 | +- Move recent posts off client `useQuery` and into route loader or server-rendered data. |
| 49 | +- Stop client-fetching OSS stats on initial paint. Render a server snapshot first. |
| 50 | +- Keep `DeferredApplicationStarter` deferred by visibility or interaction, not just idle timeout. |
| 51 | +- Avoid eagerly importing large static datasets into the first route chunk where possible. |
| 52 | +- Stop rendering both light and dark hero image variants eagerly. |
| 53 | + |
| 54 | +Expected win: |
| 55 | + |
| 56 | +- Lower homepage JS, lower hydration cost, lower first-load network. |
| 57 | + |
| 58 | +### 2. Dedicated library landing shell |
| 59 | + |
| 60 | +Targets: |
| 61 | + |
| 62 | +- `src/routes/-library-landing.tsx` |
| 63 | +- `src/components/DocsLayout.tsx` |
| 64 | +- landing components under `src/components/landing/` |
| 65 | + |
| 66 | +Changes: |
| 67 | + |
| 68 | +- Introduce a dedicated `LibraryLandingLayout`. |
| 69 | +- Remove `DocsLayout` from landing pages. |
| 70 | +- Stop fetching docs `config.json` in the landing-page critical path unless a landing section actually needs it. |
| 71 | +- Keep framework/version/docs navigation lightweight on landing pages and hand off to docs only when needed. |
| 72 | + |
| 73 | +Expected win: |
| 74 | + |
| 75 | +- Better landing-page TTFB, less landing-page JS, less docs chrome on non-docs surfaces. |
| 76 | + |
| 77 | +### 3. Docs render caching |
| 78 | + |
| 79 | +Targets: |
| 80 | + |
| 81 | +- `src/utils/docs.functions.ts` |
| 82 | +- `src/utils/github-content-cache.server.ts` |
| 83 | +- `src/utils/markdown/renderRsc.tsx` |
| 84 | +- `src/utils/markdown/processor.rsc.tsx` |
| 85 | +- `src/components/markdown/renderCodeBlock.server.tsx` |
| 86 | + |
| 87 | +Changes: |
| 88 | + |
| 89 | +- Cache rendered docs artifacts, not just raw GitHub files. |
| 90 | +- Persist `title`, `description`, `headings`, and rendered output keyed by repo, ref, docs root, and path. |
| 91 | +- Reuse existing docs artifact cache infra instead of adding a second caching path. |
| 92 | +- Make docs requests mostly cache hits unless the source changed. |
| 93 | + |
| 94 | +Expected win: |
| 95 | + |
| 96 | +- Better docs TTFB, less server CPU, fewer repeated markdown and Shiki passes. |
| 97 | + |
| 98 | +### 4. Docs layout mount discipline |
| 99 | + |
| 100 | +Targets: |
| 101 | + |
| 102 | +- `src/components/DocsLayout.tsx` |
| 103 | +- `src/components/RightRail.tsx` |
| 104 | +- `src/components/RecentPostsWidget.tsx` |
| 105 | + |
| 106 | +Changes: |
| 107 | + |
| 108 | +- Do not mount mobile docs menu on desktop. |
| 109 | +- Do not mount desktop docs menu on mobile. |
| 110 | +- Do not mount right rail when hidden by breakpoint. |
| 111 | +- Gate animated partner strip work by actual viewport and reduced-motion preference. |
| 112 | +- Ensure hidden rails do not issue queries or observers. |
| 113 | + |
| 114 | +Expected win: |
| 115 | + |
| 116 | +- Lower docs runtime cost, especially on mobile. |
| 117 | + |
| 118 | +### 5. Remove anonymous auth work from docs and landing |
| 119 | + |
| 120 | +Targets: |
| 121 | + |
| 122 | +- `src/components/FrameworkSelect.tsx` |
| 123 | +- `src/hooks/useCurrentUser.ts` |
| 124 | +- `src/components/SearchModal.tsx` |
| 125 | +- `src/components/NavbarAuthControls.tsx` |
| 126 | + |
| 127 | +Changes: |
| 128 | + |
| 129 | +- Make framework preference local-first for anonymous users. |
| 130 | +- Only sync framework preference to server when user state is already known. |
| 131 | +- Avoid triggering `getCurrentUser` on docs and landing pages just to resolve a preference. |
| 132 | +- Audit other shell components for accidental auth fetches during anonymous browsing. |
| 133 | + |
| 134 | +Expected win: |
| 135 | + |
| 136 | +- Fewer unnecessary client requests, cleaner anonymous docs navigation. |
| 137 | + |
| 138 | +### 6. Shared shell cleanup |
| 139 | + |
| 140 | +Targets: |
| 141 | + |
| 142 | +- `src/routes/__root.tsx` |
| 143 | +- `src/router.tsx` |
| 144 | +- `src/components/Navbar.tsx` |
| 145 | +- `src/components/markdown/MarkdownContent.tsx` |
| 146 | + |
| 147 | +Changes: |
| 148 | + |
| 149 | +- Verify why some intended dynamic imports are not splitting effectively. |
| 150 | +- Trim eager shell work around Sentry boot where possible. |
| 151 | +- Fix `MarkdownContent` so `CopyPageDropdown` only loads on real interaction. |
| 152 | +- Review navbar asset duplication and avoid eager light/dark image duplication where possible. |
| 153 | + |
| 154 | +Expected win: |
| 155 | + |
| 156 | +- Smaller app shell, less global cost paid by every route. |
| 157 | + |
| 158 | +## Suggested Implementation Order |
| 159 | + |
| 160 | +1. Fix obviously accidental eager work. |
| 161 | +2. Make docs layout mount only what is visible. |
| 162 | +3. Remove anonymous auth fetches from docs and landing flows. |
| 163 | +4. Add dedicated library landing shell and remove docs-config from landing critical path. |
| 164 | +5. Move homepage content and stats to server-first data flows and split below-the-fold sections. |
| 165 | +6. Add rendered docs artifact caching. |
| 166 | +7. Rebuild and compare chunks, request timings, and interaction cost. |
| 167 | + |
| 168 | +## PR Breakdown |
| 169 | + |
| 170 | +### PR 1 |
| 171 | + |
| 172 | +- Fix `MarkdownContent` eager copy-dropdown load |
| 173 | +- Stop hidden docs rails and menus from mounting |
| 174 | +- Gate mobile partner strip animation correctly |
| 175 | + |
| 176 | +### PR 2 |
| 177 | + |
| 178 | +- Remove anonymous auth fetches from framework selection and related docs shell code |
| 179 | + |
| 180 | +### PR 3 |
| 181 | + |
| 182 | +- Add `LibraryLandingLayout` |
| 183 | +- Remove `DocsLayout` and docs config dependency from landing critical path |
| 184 | + |
| 185 | +### PR 4 |
| 186 | + |
| 187 | +- Split homepage below the fold |
| 188 | +- Server-render recent posts and stats |
| 189 | +- Tighten app-starter deferral |
| 190 | + |
| 191 | +### PR 5 |
| 192 | + |
| 193 | +- Cache rendered docs artifacts |
| 194 | +- Measure docs TTFB and server CPU improvement |
| 195 | + |
| 196 | +### PR 6 |
| 197 | + |
| 198 | +- Shared shell follow-up: Sentry boot, navbar assets, remaining bundle outliers |
| 199 | + |
| 200 | +## Verification |
| 201 | + |
| 202 | +- Run `pnpm build` after each major phase. |
| 203 | +- Track homepage, a representative library landing page, and a representative docs page. |
| 204 | +- Compare: |
| 205 | +- route chunk size |
| 206 | +- app shell size |
| 207 | +- docs TTFB |
| 208 | +- number of client requests on first load |
| 209 | +- whether anonymous docs visits trigger user/auth requests |
| 210 | +- smoke-check desktop and mobile docs navigation |
| 211 | + |
| 212 | +## Notes |
| 213 | + |
| 214 | +- `LazyLandingCommunitySection` and `LazySponsorSection` already use the right pattern. Reuse that pattern more aggressively. |
| 215 | +- `StackBlitzEmbed` is already `loading="lazy"`, but a poster-plus-click model may still be worth it for landing pages. |
| 216 | +- Do not spend time micro-optimizing heading observers or tiny docs chunks before fixing the homepage and landing-page architecture. |
0 commit comments