From 986f168d322d7d7dac7197cce83fe1fdcbfbf9af Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 24 Mar 2026 11:46:16 +0100 Subject: [PATCH] feat(manascore): add Lighthouse score integration Add optional lighthouse scores (performance, accessibility, best practices, SEO) to schema. Display as inline badges on overview and circular gauges on detail page with average score. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../apps/landing/src/content/config.ts | 9 ++++ .../content/manascore/2026-03-19-calendar.md | 5 ++ .../src/content/manascore/2026-03-19-todo.md | 5 ++ .../landing/src/pages/manascore/[slug].astro | 51 +++++++++++++++++++ .../landing/src/pages/manascore/index.astro | 28 ++++++++++ 5 files changed, 98 insertions(+) diff --git a/apps/manacore/apps/landing/src/content/config.ts b/apps/manacore/apps/landing/src/content/config.ts index f9c24b494..5fd2b7922 100644 --- a/apps/manacore/apps/landing/src/content/config.ts +++ b/apps/manacore/apps/landing/src/content/config.ts @@ -203,6 +203,15 @@ const manascoreCollection = defineCollection({ security: z.number().min(0).max(100), ux: z.number().min(0).max(100), }), + // Lighthouse scores (0-100, from Google Lighthouse audit) + lighthouse: z + .object({ + performance: z.number().min(0).max(100), + accessibility: z.number().min(0).max(100), + bestPractices: z.number().min(0).max(100), + seo: z.number().min(0).max(100), + }) + .optional(), // Score history for trend visualization history: z .array( diff --git a/apps/manacore/apps/landing/src/content/manascore/2026-03-19-calendar.md b/apps/manacore/apps/landing/src/content/manascore/2026-03-19-calendar.md index 51c017d18..8eeb0ba8e 100644 --- a/apps/manacore/apps/landing/src/content/manascore/2026-03-19-calendar.md +++ b/apps/manacore/apps/landing/src/content/manascore/2026-03-19-calendar.md @@ -18,6 +18,11 @@ scores: documentation: 98 security: 92 ux: 95 +lighthouse: + performance: 92 + accessibility: 95 + bestPractices: 96 + seo: 100 status: 'production' version: '1.1.0' stats: diff --git a/apps/manacore/apps/landing/src/content/manascore/2026-03-19-todo.md b/apps/manacore/apps/landing/src/content/manascore/2026-03-19-todo.md index af1d13587..ae5c2e9e8 100644 --- a/apps/manacore/apps/landing/src/content/manascore/2026-03-19-todo.md +++ b/apps/manacore/apps/landing/src/content/manascore/2026-03-19-todo.md @@ -18,6 +18,11 @@ scores: documentation: 95 security: 90 ux: 94 +lighthouse: + performance: 90 + accessibility: 93 + bestPractices: 96 + seo: 100 status: 'production' version: '1.1.0' stats: diff --git a/apps/manacore/apps/landing/src/pages/manascore/[slug].astro b/apps/manacore/apps/landing/src/pages/manascore/[slug].astro index 3bb58aedd..b5814fbcb 100644 --- a/apps/manacore/apps/landing/src/pages/manascore/[slug].astro +++ b/apps/manacore/apps/landing/src/pages/manascore/[slug].astro @@ -223,6 +223,57 @@ function getBarColor(score: number): string { + {/* Lighthouse Scores */} + { + audit.data.lighthouse && + (() => { + const lh = audit.data.lighthouse; + const lighthouseItems = [ + { key: 'Performance', value: lh.performance, icon: '⚡' }, + { key: 'Accessibility', value: lh.accessibility, icon: '♿' }, + { key: 'Best Practices', value: lh.bestPractices, icon: '✅' }, + { key: 'SEO', value: lh.seo, icon: '🔍' }, + ]; + const avg = Math.round( + (lh.performance + lh.accessibility + lh.bestPractices + lh.seo) / 4 + ); + + return ( +
+
+
+

Lighthouse Scores

+

+ Google Lighthouse Performance Audit +

+
+ Ø {avg} +
+
+ {lighthouseItems.map(({ key, value, icon }) => ( +
+
= 90 + ? 'border-emerald-500' + : value >= 50 + ? 'border-yellow-500' + : 'border-red-500' + }`} + > + {value} +
+ + {icon} {key} + +
+ ))} +
+
+ ); + })() + } + {/* Stats */} { audit.data.stats && ( diff --git a/apps/manacore/apps/landing/src/pages/manascore/index.astro b/apps/manacore/apps/landing/src/pages/manascore/index.astro index 8cd22740a..b04385372 100644 --- a/apps/manacore/apps/landing/src/pages/manascore/index.astro +++ b/apps/manacore/apps/landing/src/pages/manascore/index.astro @@ -172,6 +172,34 @@ const statuses = [...new Set(sortedAudits.map((a) => a.data.status))]; ))} + {/* Lighthouse scores */} + {data.lighthouse && ( +
+ Lighthouse: + {Object.entries(data.lighthouse).map(([key, value]) => { + const label = + key === 'bestPractices' + ? 'BP' + : key === 'performance' + ? 'Perf' + : key === 'accessibility' + ? 'A11y' + : 'SEO'; + const color = + value >= 90 + ? 'text-emerald-500' + : value >= 50 + ? 'text-yellow-500' + : 'text-red-500'; + return ( + + {label}: {value} + + ); + })} +
+ )} + {/* Stats row */} {data.stats && (