Skip to content

[V2 200pts] Optimise images, fonts, and lazy loading to improve Core Web Vitals on landing page and dashboard #245

Description

@portableDD

Summary

Optimise images, fonts, and critical rendering path to achieve good Core Web Vitals scores (LCP < 2.5s, CLS < 0.1, INP < 200ms) on the landing page and dashboard. Poor performance on the NGN/African mobile network is a real user impact.

What Needs to Be Done

1. Replace all <img> tags with Next.js <Image />

  • Audit every <img> tag in the codebase
  • Replace with next/image <Image /> with correct width, height, and alt
  • Use priority prop on above-the-fold images (hero, logo)
  • Use loading="lazy" (default) on below-the-fold images

2. Self-host fonts

  • Remove any Google Fonts <link> tags (network request adds latency)
  • Use next/font/google which self-hosts automatically:
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'], display: 'swap' })
  • Apply font class to <html> in app/layout.tsx

3. Lazy load heavy components

  • recharts charts in admin analytics → use dynamic() with ssr: false
  • QR code component on deposit page → use dynamic() with ssr: false
  • MoonPay widget → load only when user clicks the button
const RevenueChart = dynamic(() => import('@/components/admin/revenue-chart'), { ssr: false })

4. Add next.config.ts optimisations

const config = {
  images: {
    formats: ['image/avif', 'image/webp'],
    minimumCacheTTL: 60,
  },
  compress: true,
}

5. Measure and document

  • Run Lighthouse on / and /dashboard before and after changes
  • Document LCP, CLS, INP scores before and after in the PR description

Acceptance Criteria

  • No raw <img> tags anywhere in the codebase — all use next/image
  • Fonts loaded via next/font — no external font <link> tags
  • Recharts and QR code components lazy-loaded via dynamic()
  • Lighthouse performance score ≥ 80 on landing page
  • PR description includes before/after Lighthouse scores
  • npm run build and npm run lint pass

⚠️ IMPORTANT — READ BEFORE SUBMITTING YOUR PR
Your pull request MUST target the v2 branch.
PRs targeting main or any other branch will not be reviewed and will not be merged.
Double-check your base branch before opening the PR:

Base branch: v2   ✅
Base branch: main ❌  → will be closed without review

Complexity: High — 200 points

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions