diff --git a/apps/manacore/apps/landing/src/data/ecosystem-health.json b/apps/manacore/apps/landing/src/data/ecosystem-health.json new file mode 100644 index 000000000..d9561c6cd --- /dev/null +++ b/apps/manacore/apps/landing/src/data/ecosystem-health.json @@ -0,0 +1,248 @@ +{ + "generatedAt": "2026-03-31T11:53:48.040Z", + "overallScore": 76, + "scores": { + "sharedPackages": 90, + "iconConsistency": 89, + "modalConsistency": 24, + "errorHandling": 20, + "i18nCoverage": 86, + "localFirst": 93, + "styleConsistency": 87 + }, + "weights": { + "sharedPackages": 25, + "iconConsistency": 15, + "modalConsistency": 10, + "errorHandling": 10, + "i18nCoverage": 15, + "localFirst": 10, + "styleConsistency": 15 + }, + "details": { + "icons": { + "adoption": 89, + "phosphorFiles": 353, + "inlineSvgFiles": 45, + "perApp": { + "calc": { + "phosphor": 1, + "inlineSvg": 0 + }, + "calendar": { + "phosphor": 34, + "inlineSvg": 0 + }, + "chat": { + "phosphor": 18, + "inlineSvg": 0 + }, + "citycorners": { + "phosphor": 9, + "inlineSvg": 0 + }, + "clock": { + "phosphor": 3, + "inlineSvg": 7 + }, + "contacts": { + "phosphor": 27, + "inlineSvg": 4 + }, + "context": { + "phosphor": 13, + "inlineSvg": 0 + }, + "inventar": { + "phosphor": 12, + "inlineSvg": 1 + }, + "manacore": { + "phosphor": 34, + "inlineSvg": 25 + }, + "manadeck": { + "phosphor": 2, + "inlineSvg": 1 + }, + "manavoxel": { + "phosphor": 0, + "inlineSvg": 0 + }, + "matrix": { + "phosphor": 26, + "inlineSvg": 0 + }, + "moodlit": { + "phosphor": 5, + "inlineSvg": 0 + }, + "mukke": { + "phosphor": 21, + "inlineSvg": 0 + }, + "news": { + "phosphor": 1, + "inlineSvg": 0 + }, + "nutriphi": { + "phosphor": 6, + "inlineSvg": 1 + }, + "photos": { + "phosphor": 11, + "inlineSvg": 3 + }, + "picture": { + "phosphor": 27, + "inlineSvg": 0 + }, + "planta": { + "phosphor": 0, + "inlineSvg": 0 + }, + "playground": { + "phosphor": 4, + "inlineSvg": 1 + }, + "presi": { + "phosphor": 6, + "inlineSvg": 0 + }, + "questions": { + "phosphor": 7, + "inlineSvg": 0 + }, + "skilltree": { + "phosphor": 12, + "inlineSvg": 1 + }, + "storage": { + "phosphor": 25, + "inlineSvg": 1 + }, + "times": { + "phosphor": 13, + "inlineSvg": 0 + }, + "todo": { + "phosphor": 22, + "inlineSvg": 0 + }, + "uload": { + "phosphor": 3, + "inlineSvg": 0 + }, + "wisekeep": { + "phosphor": 2, + "inlineSvg": 0 + }, + "zitare": { + "phosphor": 9, + "inlineSvg": 0 + } + } + }, + "modals": { + "adoption": 24, + "total": 51, + "sharedUsage": 12, + "focusTrapUsage": 7 + }, + "packages": { + "coreAdoption": 90, + "totalApps": 29, + "perPackage": { + "Auth": { + "count": 29, + "total": 29, + "adoption": 100 + }, + "UI": { + "count": 28, + "total": 29, + "adoption": 97 + }, + "Theme": { + "count": 24, + "total": 29, + "adoption": 83 + }, + "Branding": { + "count": 28, + "total": 29, + "adoption": 97 + }, + "i18n": { + "count": 23, + "total": 29, + "adoption": 79 + }, + "Error Tracking": { + "count": 24, + "total": 29, + "adoption": 83 + }, + "Icons": { + "count": 25, + "total": 29, + "adoption": 86 + }, + "Local Store": { + "count": 27, + "total": 29, + "adoption": 93 + } + } + }, + "errors": { + "adoption": 20, + "inline": 193, + "shared": 47 + }, + "i18n": { + "adoption": 86, + "withI18n": 25, + "without": 4 + }, + "localFirst": { + "adoption": 93, + "count": 27 + }, + "styles": { + "themeAdoption": 83, + "tailwindAdoption": 90 + } + }, + "apps": [ + "calc", + "calendar", + "chat", + "citycorners", + "clock", + "contacts", + "context", + "inventar", + "manacore", + "manadeck", + "manavoxel", + "matrix", + "moodlit", + "mukke", + "news", + "nutriphi", + "photos", + "picture", + "planta", + "playground", + "presi", + "questions", + "skilltree", + "storage", + "times", + "todo", + "uload", + "wisekeep", + "zitare" + ] +} diff --git a/apps/manacore/apps/landing/src/pages/manascore/ecosystem.astro b/apps/manacore/apps/landing/src/pages/manascore/ecosystem.astro new file mode 100644 index 000000000..346d0dea2 --- /dev/null +++ b/apps/manacore/apps/landing/src/pages/manascore/ecosystem.astro @@ -0,0 +1,252 @@ +--- +import Layout from '../../layouts/Layout.astro'; +import Navbar from '../../components/navigation/Navbar.astro'; +import Footer from '../../components/navigation/Footer.astro'; +import Section from '../../components/content/Section.astro'; +import Container from '../../components/layout/Container.astro'; +import HeroSection from '../../components/content/HeroSection.astro'; +import ecosystemData from '../../data/ecosystem-health.json'; + +const { overallScore, scores, weights, details } = ecosystemData; + +function getScoreColor(score: number): string { + if (score >= 85) return 'text-emerald-500'; + if (score >= 70) return 'text-green-500'; + if (score >= 50) return 'text-yellow-500'; + if (score >= 30) return 'text-orange-500'; + return 'text-red-500'; +} + +function getBarColor(score: number): string { + if (score >= 85) return 'bg-emerald-500'; + if (score >= 70) return 'bg-green-500'; + if (score >= 50) return 'bg-yellow-500'; + if (score >= 30) return 'bg-orange-500'; + return 'bg-red-500'; +} + +function getBarBg(score: number): string { + if (score >= 85) return 'bg-emerald-500/10'; + if (score >= 70) return 'bg-green-500/10'; + if (score >= 50) return 'bg-yellow-500/10'; + if (score >= 30) return 'bg-orange-500/10'; + return 'bg-red-500/10'; +} + +const categories = [ + { + key: 'sharedPackages', + label: 'Shared Packages', + icon: '📦', + description: 'Adoption der 6 Core-Packages über alle Apps', + }, + { + key: 'iconConsistency', + label: 'Icon Consistency', + icon: '🎨', + description: 'Phosphor Icons vs inline SVGs', + }, + { + key: 'modalConsistency', + label: 'Modal Consistency', + icon: '🪟', + description: 'shared-ui Modal vs Custom-Implementierungen', + }, + { + key: 'errorHandling', + label: 'Error Handling', + icon: '⚠️', + description: 'Shared Helper vs inline instanceof Error', + }, + { + key: 'i18nCoverage', + label: 'i18n Coverage', + icon: '🌍', + description: 'Apps mit Internationalisierung', + }, + { + key: 'localFirst', + label: 'Local-First', + icon: '💾', + description: 'Apps mit Offline-fähigem Local Store', + }, + { + key: 'styleConsistency', + label: 'Style Consistency', + icon: '🎭', + description: 'Theme-Variablen + Tailwind CSS Nutzung', + }, +]; + +const packageDetails = details.packages.perPackage; +const generatedDate = new Date(ecosystemData.generatedAt).toLocaleDateString('de-DE', { + day: 'numeric', + month: 'long', + year: 'numeric', +}); +--- + + + + + + +
+ +
+ +
+
+ {overallScore} +
+
Ecosystem Health Score
+
+ {details.packages.totalApps} Web Apps analysiert · Stand: {generatedDate} +
+
+ + +
+

Score Breakdown

+ + { + categories.map(({ key, label, icon, description }) => { + const score = scores[key as keyof typeof scores]; + const weight = weights[key as keyof typeof weights]; + return ( +
+
+
+ {icon} +
+
{label}
+
{description}
+
+
+
+ Gewicht: {weight}% + {score}% +
+
+
+
+
+
+ ); + }) + } +
+ + +
+

Shared Package Adoption

+
+ { + Object.entries(packageDetails).map(([name, data]: [string, any]) => ( +
+
+ {data.adoption}% +
+
{name}
+
+ {data.count}/{data.total} Apps +
+
+ )) + } +
+
+ + +
+

Icon Consistency Details

+
+
+
{details.icons.phosphorFiles}
+
Dateien mit Phosphor Icons
+
+
+
0 ? 'text-orange-500' : 'text-emerald-500'}`} + > + {details.icons.inlineSvgFiles} +
+
Dateien mit Inline SVGs
+
+
+
+ + +
+

Modal Consistency

+
+
+
{details.modals.total}
+
Modals gesamt
+
+
+
{details.modals.sharedUsage}
+
Nutzen shared-ui Modal
+
+
+
{details.modals.focusTrapUsage}
+
Mit focusTrap (A11y)
+
+
+
+ + +
+

Error Handling Patterns

+
+
+
{details.errors.shared}
+
Shared Helper Nutzungen
+
+
+
20 ? 'text-orange-500' : 'text-yellow-500'}`} + > + {details.errors.inline} +
+
Inline instanceof Error
+
+
+
+ + + +
+ +
+ +