mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 07:41:09 +02:00
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) <noreply@anthropic.com>
This commit is contained in:
parent
e06e8cca59
commit
986f168d32
5 changed files with 98 additions and 0 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -223,6 +223,57 @@ function getBarColor(score: number): string {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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 (
|
||||
<div class="border-border/50 mb-8 rounded-xl border bg-gradient-to-br from-white/5 to-white/[0.02] p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h2 class="text-foreground text-sm font-semibold">Lighthouse Scores</h2>
|
||||
<p class="text-muted-foreground text-xs">
|
||||
Google Lighthouse Performance Audit
|
||||
</p>
|
||||
</div>
|
||||
<span class={`text-lg font-bold ${getScoreColor(avg)}`}>Ø {avg}</span>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 sm:grid-cols-4">
|
||||
{lighthouseItems.map(({ key, value, icon }) => (
|
||||
<div class="text-center">
|
||||
<div
|
||||
class={`relative mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-full border-4 ${
|
||||
value >= 90
|
||||
? 'border-emerald-500'
|
||||
: value >= 50
|
||||
? 'border-yellow-500'
|
||||
: 'border-red-500'
|
||||
}`}
|
||||
>
|
||||
<span class={`text-lg font-bold ${getScoreColor(value)}`}>{value}</span>
|
||||
</div>
|
||||
<span class="text-muted-foreground text-[11px]">
|
||||
{icon} {key}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})()
|
||||
}
|
||||
|
||||
{/* Stats */}
|
||||
{
|
||||
audit.data.stats && (
|
||||
|
|
|
|||
|
|
@ -172,6 +172,34 @@ const statuses = [...new Set(sortedAudits.map((a) => a.data.status))];
|
|||
))}
|
||||
</div>
|
||||
|
||||
{/* Lighthouse scores */}
|
||||
{data.lighthouse && (
|
||||
<div class="mt-2 flex items-center gap-3">
|
||||
<span class="text-muted-foreground/50 text-[9px]">Lighthouse:</span>
|
||||
{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 (
|
||||
<span class={`text-[10px] font-medium ${color}`} title={key}>
|
||||
{label}: {value}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Stats row */}
|
||||
{data.stats && (
|
||||
<div class="text-muted-foreground/60 mt-2 flex flex-wrap gap-3 text-[10px]">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue