Goal this serves — Donors on slow connections completing donations
Why this matters
Every page loads 349 kB of shared JavaScript before rendering. On a fast connection that is invisible; on a mid-range phone over mobile data — which is how a large share of donors worldwide browse — it is many seconds of blank screen before a project page is usable.
For a platform whose purpose is collecting donations, that delay sits directly in front of the conversion step. Nothing currently measures it, so it can regress indefinitely without anyone noticing.
Evidence
First Load JS shared by all 349 kB
chunks/pages/_app-*.js 258 kB
The application shell alone is 258 kB. Contributing factors are visible in the dependency set: the full Stellar SDK, a charting library, a 3D rendering library for the network graph, and an internationalisation message formatter — several of which are needed on a small number of routes but are paid for on all of them.
No budget is enforced anywhere in CI, and no Core Web Vitals measurement exists.
Why this is hard
The heavy dependencies are load-bearing. The Stellar SDK is required to build and sign transactions, and cannot simply be dropped — it has to be deferred to the point of use without breaking the donation flow or reintroducing a delay at the worst moment.
Server-side rendering is mandatory here. _app.tsx forces it so the CSP nonce reaches every script, which constrains which optimisations are available.
Budgets need enforcement to matter. A measured number that does not fail a build regresses within weeks.
Field data differs from lab data. Synthetic measurements miss what real donors experience, and the metric that matters — whether donations complete — is not a bundle size.
Suggested approach
Establish budgets per route and enforce them in CI so a regression fails the build with a clear diff of what grew.
Defer route-specific heavy dependencies to their point of use, taking particular care that the donation flow does not simply move its delay to the moment of signing.
Measure Core Web Vitals in the field rather than only in the lab, and connect the result to donation completion so the work is justified by outcome rather than by a number going down.
Acceptance criteria
Scope
Roughly 5,000–7,000 lines, including tests.
Relevant files
frontend/next.config.mjs
frontend/pages/_app.tsx
frontend/components/TransactionGraphVisualizer.tsx
frontend/lib/stellar.ts
.github/workflows/ci.yml
Why this matters
Every page loads 349 kB of shared JavaScript before rendering. On a fast connection that is invisible; on a mid-range phone over mobile data — which is how a large share of donors worldwide browse — it is many seconds of blank screen before a project page is usable.
For a platform whose purpose is collecting donations, that delay sits directly in front of the conversion step. Nothing currently measures it, so it can regress indefinitely without anyone noticing.
Evidence
The application shell alone is 258 kB. Contributing factors are visible in the dependency set: the full Stellar SDK, a charting library, a 3D rendering library for the network graph, and an internationalisation message formatter — several of which are needed on a small number of routes but are paid for on all of them.
No budget is enforced anywhere in CI, and no Core Web Vitals measurement exists.
Why this is hard
The heavy dependencies are load-bearing. The Stellar SDK is required to build and sign transactions, and cannot simply be dropped — it has to be deferred to the point of use without breaking the donation flow or reintroducing a delay at the worst moment.
Server-side rendering is mandatory here.
_app.tsxforces it so the CSP nonce reaches every script, which constrains which optimisations are available.Budgets need enforcement to matter. A measured number that does not fail a build regresses within weeks.
Field data differs from lab data. Synthetic measurements miss what real donors experience, and the metric that matters — whether donations complete — is not a bundle size.
Suggested approach
Establish budgets per route and enforce them in CI so a regression fails the build with a clear diff of what grew.
Defer route-specific heavy dependencies to their point of use, taking particular care that the donation flow does not simply move its delay to the moment of signing.
Measure Core Web Vitals in the field rather than only in the lab, and connect the result to donation completion so the work is justified by outcome rather than by a number going down.
Acceptance criteria
Scope
Roughly 5,000–7,000 lines, including tests.
Relevant files
frontend/next.config.mjsfrontend/pages/_app.tsxfrontend/components/TransactionGraphVisualizer.tsxfrontend/lib/stellar.ts.github/workflows/ci.yml