Landing Page
WebApp Implementation: Modern Next.js Architecture für Self-Hosted Cloud
Inhaltsverzeichnis
Einleitung
Die matzka.cloud WebApp ist eine vollständig integrierte Next.js-Anwendung, die als Frontend für unser Self-Hosted Cloud-Ökosystem fungiert. In diesem ausführlichen Beitrag beschreiben wir die komplette Architektur, Design-Prinzipien, Komponenten und technische Implementierungsdetails dieser modernen Web-Anwendung.
Die WebApp verbindet mehrere Dienste unserer Infrastruktur (Directus CMS, Prometheus Monitoring, n8n Automation) in einer einzigen, kohärenten Benutzeroberfläche.
1. Architektur-Überblick
1.1 Technology Stack
Frontend Stack:
├── Next.js 16.1.1 (App Router)
├── React 19.2.0
├── TypeScript 5.9+
├── Tailwind CSS 4.1+
└── shadcn/ui Component Library
Data & Integration:
├── Directus CMS (Headless CMS)
├── Prometheus (Metrics)
├── n8n (Workflow Automation)
└── Recharts 3.3.0 (Visualizations)
Development Tools:
├── ESLint + Prettier
├── Playwright (E2E Tests)
├── npm (Package Management)
└── Docker (Containerization)
Infrastructure:
├── Docker Container
├── PostgreSQL 17 (Directus Database)
├── Traefik Reverse Proxy
└── Let's Encrypt SSL/TLS
1.2 Design-Philosophie
Die WebApp folgt folgenden Designprinzipien:
- Server-First Architecture
- React Server Components für maximale Performance
- Statische Seiten-Generierung wo möglich (SSG)
- Incremental Static Regeneration (ISR) für dynamische Inhalte
- Component-Driven Development
- shadcn/ui als basis für konsistente, barrierefreie UI
- Reusable components mit TypeScript type safety
- Compound components für komplexe UI-Strukturen
- Performance-Focused
- Image optimization mit Next.js Image Component
- Lazy loading für offscreen content
- 15-Sekunden ISR-Cache für Inhalte von Directus
- Next.js built-in optimizations (code splitting, tree shaking)
- Responsive & Accessible
- Mobile-first CSS-Design
- WCAG 2.1 AA compliance
- Semantic HTML5 und ARIA labels
- Dark mode support via CSS variables
2. Seiten-Struktur & Routing
2.1 Seiten-Übersicht
matzka.cloud/
├── / (Homepage)
│ ├── Hero Section
│ ├── Features Overview
│ ├── Service Status Widget
│ └── Call-to-Action Buttons
│
├── /blog (Blog Listing)
│ ├── Blog Grid
│ ├── Search/Filter
│ └── Pagination
│
├── /blog/[slug] (Individual Post)
│ ├── Dynamic Content from Directus
│ ├── Custom Blog Styling
│ └── Related Posts
│
├── /status (Service Status)
│ ├── Real-time Service Monitoring
│ ├── Response Times
│ └── Status Indicators
│
├── /performance (System Performance) ⭐ NEW
│ ├── CPU Usage Gauge
│ ├── Memory Usage Gauge
│ ├── Disk Usage Gauge
│ ├── Real-time Updates (15s)
│ └── Status Indicators
│
├── /contact (Contact Form)
│ ├── Form Validation (React Hook Form + Zod)
│ ├── n8n Webhook Integration
│ └── Success/Error Messages
│
└── /datenschutz (Privacy Policy)
└── Static Content
2.2 Routing mit App Router
Die WebApp nutzt das moderne Next.js 16 App Router mit File-based Routing:
// Datei-Struktur entspricht URL-Struktur
app/
├── page.tsx // Route: /
├── layout.tsx // Root layout mit Header/Footer
├── globals.css // Global styles
├── blog/
│ ├── page.tsx // Route: /blog
│ ├── layout.tsx // Blog layout
│ └── [slug]/
│ └── page.tsx // Route: /blog/[slug]
├── status/
│ └── page.tsx // Route: /status
├── performance/ // ⭐ NEW
│ └── page.tsx // Route: /performance
├── contact/
│ └── page.tsx // Route: /contact
├── datenschutz/
│ └── page.tsx // Route: /datenschutz
└── api/
└── prometheus/ // ⭐ NEW API Route
└── route.ts // GET /api/prometheus
3. Performance Monitoring Feature (Highlight)
3.1 Übersicht
Die neu implementierte Performance-Seite zeigt in Echtzeit Metriken des Host-Systems an. Diese Seite demonstriert die Integration von Prometheus mit der WebApp.
3.2 Architektur
┌──────────────────────────────┐
│ Performance Page (SSG) │
│ app/performance/page.tsx │
└────────────┬─────────────────┘
│ (renders)
┌────────────▼──────────────────┐
│ PerformanceMonitor (Client) │
│ components/performance/... │
│ - Real-time polling (15s) │
│ - State management │
│ - Error handling │
└────────────┬─────────────────┘
│ (fetches every 15s)
┌────────────▼──────────────────┐
│ Prometheus API Route │
│ app/api/prometheus/route.ts │
│ - Server-side PromQL queries │
│ - ISR Caching (15s) │
│ - Error handling │
└────────────┬─────────────────┘
│ (queries)
┌────────────▼──────────────────┐
│ Prometheus Server │
│ http://prometheus:9090 │
│ - Node Exporter Metrics │
│ - 15s Scrape Interval │
└──────────────────────────────┘
3.3 Angezeigte Metriken
| Metrik | Status | Beschreibung |
|---|---|---|
| CPU Auslastung | ✅ | Prozessorauslastung aller Cores, 5-Min Durchschnitt |
| System Load | ✅ | 1-Min Load normalisiert auf 4 CPUs |
| RAM Auslastung | ✅ | Arbeitsspeicher-Nutzung |
| SWAP Auslastung | ⚠️ | Nur wenn konfiguriert |
| Root FS Auslastung | ✅ | Festplatten-Auslastung der Root-Partition |
3.4 Status-Indikatoren
Normal (< 70%): 🟢 Grün oklch(0.6 0.118 142.5)
Warning (70-90%): 🟡 Gelb oklch(0.828 0.189 84.429)
Critical (> 90%): 🔴 Rot oklch(0.577 0.245 27.325)
Unknown (N/A): ⚪ Grau oklch(0.65 0 0)
4. Komponenten-Architektur
4.1 Komponenten-Hierarchie
app/
├── (Root Layout)
│ ├── Header (Navigation)
│ │ └── Links: [Home, Blog, Status, Performance, Kontakt]
│ ├── (Page Content)
│ │ └── Various page-specific components
│ └── Footer
│
└── Components
├── performance/
│ ├── PerformanceMonitor.tsx (Client, Real-time)
│ ├── MetricsGrid.tsx (Client, Layout)
│ └── MetricGauge.tsx (Client, Visualization)
│
├── blog/
│ ├── BlogGrid.tsx
│ └── BlogCard.tsx
│
├── ServiceStatus.tsx (Status Page)
├── ContactForm.tsx (Contact Page)
├── Header.tsx (Global Navigation)
└── Footer.tsx (Global Footer)
4.2 Component Patterns
Server Components (Default)
// Page components sind automatisch Server Components
// Ermöglichen:
// - Direkte Datenbankzugriffe
// - API-Token Sicherheit
// - Reduced JS bundle size
// - ISR caching
export default async function BlogPage() {
const posts = await fetchFromDirectus();
return <BlogGrid posts={posts} />;
}
Client Components (Interaktiv)
'use client'; // Explizit als Client Component
import { useEffect, useState } from 'react';
export default function PerformanceMonitor() {
const [metrics, setMetrics] = useState(null);
useEffect(() => {
// Polling logic
}, []);
return <MetricsGrid metrics={metrics} />;
}
<Card>
<CardHeader>
<CardTitle>Metric Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>
{/* Content */}
</CardContent>
<CardFooter>
{/* Footer */}
</CardFooter>
</Card>
5. Daten-Integration
5.1 Directus CMS Integration
Blog-Inhalte und Metadaten kommen aus Directus CMS:
// Server Component - Direkter Datenbankzugriff
async function getBlogPosts() {
const cmsUrl = process.env.NEXT_PUBLIC_CMS_URL;
const apiToken = process.env.CMS_API_TOKEN;
const response = await fetch(
`${cmsUrl}/items/blog_posts`,
{
headers: {
'Authorization': `Bearer ${apiToken}`,
'Content-Type': 'application/json'
},
next: { revalidate: 60 } // ISR: revalidate jeden 60s
}
);
return response.json();
}
- ✅ API-Token bleibt server-side (sicher)
- ✅ Statische Seiten-Generierung
- ✅ Inkrementelle Updates (ISR)
- ✅ Keine redundanten API-Calls
- ✅ Bessere Performance durch Caching
5.2 Prometheus API Integration
System-Metriken werden über eine dedizierte API Route abgefragt:
// app/api/prometheus/route.ts
export async function GET() {
const metrics = await fetchMetrics();
return NextResponse.json(metrics, {
headers: { 'Cache-Control': 'private, max-age=15' }
});
}
PromQL-Queries:
# CPU Usage (all cores, 5-min avg)
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# System Load (normalized to 4 CPUs)
node_load1 * 100 / 4
# Memory Usage (available vs total)
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
# Disk Usage (root partition)
(1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100
5.3 n8n Webhook Integration
Kontakt-Formular sendet Daten an n8n Automation:
// components/ContactForm.tsx
const handleSubmit = async (data) => {
const webhookUrl = process.env.NEXT_PUBLIC_CONTACT_WEBHOOK_URL;
const response = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
return response.json();
};
6. Styling & Design System
6.1 Tailwind CSS 4.1
Die WebApp nutzt Tailwind CSS 4.1 mit modernem Feature-Set:
/* globals.css - Modern Tailwind Syntax */
@import "tailwindcss";
@layer base {
:root {
/* OKLCH Color Space für präzise Farben */
--primary: oklch(0.73 0.119 258.325);
--secondary: oklch(0.8 0.037 280.356);
--destructive: oklch(0.577 0.245 27.325);
--radius: 0.5rem;
}
}
/* Custom Utilities */
@layer utilities {
.text-balance { text-wrap: balance; }
}
6.2 Responsive Design
/* Mobile-first breakpoints */
base styles /* < 640px */
md: (medium devices) /* >= 768px */
lg: (large devices) /* >= 1024px */
Example - MetricsGrid Layout:
grid-cols-1 /* 1 column on mobile */
md:grid-cols-2 /* 2 columns on tablet */
lg:grid-cols-3 /* 3 columns on desktop */
6.3 shadcn/ui Component Library
shadcn/ui bietet 45+ vorgefertigte, unstyled Components. Häufig genutzte Components:
Button,Card,Alert- Basic UITable,Badge,Progress- Data DisplayDialog,Sheet,Popover- OverlaysForm,Input,Select- Form ControlsTabs,Accordion,Collapsible- Navigation
7. Performance & Optimierungen
7.1 Bundle Size Optimization
Production Build:
├── Main JS Bundle: ~45KB (gzipped)
├── CSS Bundle: ~12KB (gzipped)
└── Images: Optimized via Next.js Image Component
Optimierungen:
✓ Tree-shaking von ungenutztem Code
✓ Code-splitting per Route
✓ Dynamic imports für große Features
✓ Image optimization (WebP, AVIF)
✓ Font subsetting (Inter font)
7.2 Caching-Strategie
┌─────────────────────────────────────┐
│ Browser Cache (ISR) │
│ 15-60 Sekunden für SSG/Inhalte │
└──────────┬──────────────────────────┘
│
┌──────────▼──────────────────────────┐
│ CDN Cache (Traefik/Reverse Proxy) │
│ 1 Stunde für statische Assets │
└──────────┬──────────────────────────┘
│
┌──────────▼──────────────────────────┐
│ Application Cache (ISR) │
│ Inkrementelle Updates im Hintergrund │
└──────────┬──────────────────────────┘
│
┌──────────▼──────────────────────────┐
│ Data Sources │
│ ├── Directus CMS (revalidate: 60) │
│ ├── Prometheus API (revalidate: 15) │
│ └── n8n Webhooks (on-demand) │
└─────────────────────────────────────┘
7.3 Performance Metriken
Mit den neuen WebVitals Optimierungen:
| Metrik | Target | Actual |
|---|---|---|
| FCP (First Contentful Paint) | < 1.8s | ~0.9s ✅ |
| LCP (Largest Contentful Paint) | < 2.5s | ~1.2s ✅ |
| CLS (Cumulative Layout Shift) | < 0.1 | ~0.02 ✅ |
| TTB (Time to Byte) | < 100ms | ~45ms ✅ |
8. Sicherheit
8.1 Security Best Practices
// ✅ API-Token auf server-side
const cmsToken = process.env.CMS_API_TOKEN; // Node.js only
// ✅ Validierung mit Zod
const schema = z.object({
name: z.string().min(2),
email: z.string().email(),
message: z.string().min(10)
});
// ✅ CSRF Protection (Next.js automatisch)
// ✅ XSS Prevention durch React's built-in escaping
// ✅ HTTP Security Headers (via Traefik)
8.2 Environment Variables
# .env (sicherheitsrelevant - nicht committen!)
DIRECTUS_API_TOKEN=... # Server-only
CMS_API_TOKEN=... # Server-only
PROMETHEUS_URL=... # Server-only
# NEXT_PUBLIC_* sind im Client sichtbar!
NEXT_PUBLIC_CMS_URL=https://cms.matzka.cloud
NEXT_PUBLIC_CONTACT_WEBHOOK_URL=https://n8n.matzka.cloud/webhook/contact
9. Testing & Quality Assurance
9.1 Type Safety
# TypeScript Strict Mode
npm run typecheck
# Validierung mit Zod
const ContactSchema = z.object({
name: z.string().min(2, "Min 2 Zeichen"),
email: z.string().email(),
message: z.string().min(10)
});
9.2 Testing & Quality Commands
# E2E Tests mit Playwright
npm run test
# Linting
npm run lint
# Type Checking
npm run typecheck
# Build Verification
npm run build
10. Deployment & Operations
10.1 Docker Deployment
# Multi-stage build
FROM node:22-alpine AS deps
RUN npm ci
FROM node:22-alpine AS builder
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build
FROM node:22-alpine AS runner
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]
10.2 Production Stack
docker-compose.yml:
postgres-directus:
image: postgres:17-alpine
volumes: [postgres_directus_data]
directus:
image: directus/directus:11.3.3
depends_on: [postgres-directus]
environment: [ADMIN_EMAIL, ADMIN_PASSWORD, ...]
webapp:
build: ./app
image: matzka-webapp:latest
environment: [CMS_API_TOKEN, PROMETHEUS_URL, ...]
labels:
traefik.enable: "true"
traefik.http.routers.webapp.rule: Host(`matzka.cloud`)
traefik.http.services.webapp.loadbalancer.server.port: 3000
10.3 Monitoring & Logs
# Container Status
docker compose ps
# Logs
docker logs -f webapp
# Metrics
https://matzka.cloud/performance
Fazit
Die matzka.cloud WebApp demonstriert moderne Web-Development Best Practices:
- ✅ Next.js 16 App Router für optimale Performance
- ✅ React Server Components für skalierbare Architektur
- ✅ TypeScript für Typ-Sicherheit
- ✅ shadcn/ui für konsistente, barrierefreie UI
- ✅ Tailwind CSS 4 für responsives Design
- ✅ Integration mit Prometheus für echtzeitliche Überwachung
- ✅ Docker für containerisierte Deployments
- ✅ Traefik für SSL/TLS und Routing
Die Implementierung zeigt, wie man moderne Frontend-Technologien mit einer self-hosted Infrastruktur kombiniert, um eine leistungsstarke, sichere und wartbare Web-Anwendung zu schaffen.