Live Core Web Vitals
Metrics captured from this sessionThese metrics are collected from your current browser session using the native PerformanceObserver API. Values are automatically logged to your Supabase database for historical tracking. CLS and INP require user interaction to fully measure.
Performance Audit Checklist
LCP — Largest Contentful Paint
Hero image is preloaded with fetchpriority='high'
index.html includes <link rel='preload' as='image'> for the hero background.
Critical fonts are loaded asynchronously
Inter, Remixicon, and FontAwesome use media='print' onload swap technique.
Third-party CSS is not render-blocking
Icon fonts and Google Fonts load via print-media swap.
Hero image has explicit width & height
Home hero has width=1280 height=720 on the <img> tag.
Blog post hero images have explicit dimensions
Blog post and blog listing hero images lack width/height attributes. Add them to prevent layout shift.
Consider responsive image sizes
Hero image loads 1280px wide for all viewports. Consider srcset for smaller screens.
CLS — Cumulative Layout Shift
Images have explicit dimensions where possible
Case study and sector cards lack width/height on images. CLS risk on slow connections.
Font loading prevents FOUT
Inter font has display=swap. Text remains invisible for max 3s then swaps.
No late-injected content without reserved space
Review banner, floating buttons, and cookie banner are fixed-position — they don't shift layout.
Blog cards below fold have reserved space
Blog cards use consistent grid sizing. Images inside containers with overflow-hidden.
FID / INP — Interaction Responsiveness
JavaScript is chunked and lazy-loaded
Vite config splits vendor, react, supabase, and mocks into separate chunks.
GTM is deferred until idle
Google Tag Manager loads via requestIdleCallback with 3s timeout.
Long tasks in main thread
Blog page generates large JSON-LD schema inline. Consider memoizing schema generation.
Event handlers are not blocking
All click handlers use smooth scroll or simple navigation. No heavy computation on click.
TTFB — Server Response
Preconnect to critical origins
Preconnect headers present for readdy.ai, fonts.gstatic.com, cdnjs.cloudflare.com.
DNS prefetch for analytics
dns-prefetch for googletagmanager.com in <head>.
Static site is pre-rendered
vite-prerender-plugin generates static HTML for all routes. TTFB is minimal.
API calls are not on critical path
Supabase data is only fetched on the SEO dashboard and product pages. Home page is static.
FCP — First Contentful Paint
Critical CSS is inlined
No critical CSS extraction. Consider adding a small inline stylesheet for above-fold content.
No render-blocking scripts in <head>
Only the module script is in <head>, and it's type='module' (async by default). GTM is deferred.
HTML is prerendered for instant paint
SSR via prerender plugin means first paint is instant HTML, not a blank white screen.
General Performance
Images use lazy loading below fold
Case study, sector, and blog cards use loading='lazy'.
Source maps enabled in build
sourcemap: true adds ~15-20% to bundle size. Disable for production builds.
No unused JavaScript dependencies
Firebase is included but unused. Recharts is only used on the SEO dashboard. Consider lazy-loading chart libs.
Compression is enabled on server
Verify Brotli or Gzip is enabled on your hosting platform. Check response headers for Content-Encoding.
Metrics History
| Metric | Value | Rating | Page | Time |
|---|---|---|---|---|
| TTFB | 770 ms | good | /core-web-vitals | 31 May, 16:14 |
| LCP | 4,837 ms | poor | /core-web-vitals | 31 May, 16:14 |
| CLS | 0.025 | good | /core-web-vitals | 31 May, 16:14 |
| FCP | 2,498 ms | Needs Work | /core-web-vitals | 31 May, 16:14 |
| FCP | 2,498 ms | Needs Work | /core-web-vitals | 31 May, 16:14 |