Ein Tool mit klarem Fokus auf Einfachheit kann komplexere Herausforderungen mit sich bringen als gedacht. Der kostenlose Brat-Generator ibratgenerator.com entstand aus der Inspiration zum Charli XCX-Album Brat und zeigt, wie Performance-Optimierungen in Next.js 16 oft unsichtbare Hürden überwinden müssen. Hier sind die wichtigsten Erkenntnisse aus der Entwicklung – von dynamischen Importen bis zur Canvas-Optimierung.
Warum ein Brat-Generator mehr ist als nur ein Tool
Die Ästhetik von Brat ist bewusst reduziert: Großbuchstaben in Kleinbuchstaben, einfarbiger Hintergrund, keine überflüssigen Elemente. Doch genau diese Klarheit machte die technische Umsetzung zu einem Experimentierfeld für Web-Performance und Nutzererlebnis. Das Tool ermöglicht es Nutzern, beliebigen Text einzugeben, Hintergrundfarben zu wählen und hochauflösende PNGs mit bis zu 3000 Pixeln Seitenlänge herunterzuladen – ohne Anmeldung, ohne Wasserzeichen und ohne komplizierte Einstellungen.
Die Kernfunktionen umfassen:
- Anpassbare Farboptionen für Hintergrund und Text
- Vorgegebene Seitenverhältnisse wie 1:1, 4:5 oder 16:9
- Sticker- und Emoji-Overlays für persönliche Akzente
- Typografie-Steuerung mit Schriftgröße, Buchstabenabstand und Ausrichtung
- Touch-Unterstützung für mobile Endgeräte
Hinter den Kulissen läuft das Tool mit Next.js 16 im App-Router-Modus und setzt auf ein selbst geschriebenes Canvas-Rendering in reinem TypeScript – ohne externe Bibliotheken.
Dynamische Importe in Next.js: Die LCP-Falle bei der Google-Crawling
Das größte Hindernis war nicht die Logik des Generators selbst, sondern die Interaktion zwischen Next.js und dem Browser. Da das Canvas-Element auf serverseitige Funktionen wie window oder document angewiesen ist, musste es clientseitig geladen werden. Die Lösung schien naheliegend: der Einsatz von next/dynamic mit der Option ssr: false.
const BratGeneratorLazy = dynamic(
() => import('./BratGenerator'),
{ ssr: false }
)Auf mobilen Geräten funktionierte das einwandfrei. Doch bei der Analyse der Google-Suchmaschinen-Crawling-Ergebnisse zeigte sich ein Problem: Die Seite erschien auf Desktop-Browsern zunächst als große leere Fläche, da Google keine clientseitig gerenderten Inhalte auswerten kann. Das hatte direkte Auswirkungen auf den Largest Contentful Paint (LCP) – ein kritischer Ranking-Faktor.
Die Lösung war simpel, aber entscheidend: Ein Container mit festgelegter Mindesthöhe und relativer Positionierung reservierte den benötigten Platz bereits vor dem Laden des Components.
<div style={{
minHeight: '520px',
position: 'relative',
width: '100%'
}}>
<BratGeneratorLazy />
</div>Diese kleine Anpassung verbesserte die Sichtbarkeit in den Google Search Console-Daten deutlich. Wichtig war dabei auch die Kombination aus position: relative und width: 100%, um Layout-Shifts und Überlappungen mit festen Headern zu vermeiden.
Canvas-Performance: Warum Referenzen statt Kopien den Unterschied machen
Eine weitere Herausforderung war die Implementierung von Rückgängig/Wiederherstellen-Funktionen. Jede Nutzerinteraktion speicherte einen Zustandsschnappschuss in einem Array. Die ursprüngliche Version erstellte dabei eine neue Image-Instanz für jedes Hintergrundbild:
// Vorher – ineffizient
bgImage: s.bgImage ? (() => {
const img = new Image();
img.src = s.bgImage!.src;
return img;
})() : nullDiese Herangehensweise führte zu Heap-Churn und spürbaren UI-Rucklern – besonders auf älteren oder schwächeren Geräten. Die Lösung lag in der direkten Referenzzuweisung:
// Nachher – optimiert
bgImage: s.bgImageDa das bgImage-Objekt zwischen den Zuständen unverändert bleibt, reicht es aus, die Referenz zu kopieren. Dies eliminiert unnötige DOM-Instantiierungen und entlastet den JavaScript-Heap deutlich.
Event-Listener: Warum doppelte Handler in React StrictMode gefährlich sind
Für die Sticker-Verschiebung wurden globale Pointer-Events an das window-Objekt gebunden:
window.addEventListener("pointermove", onPointerMove)
window.addEventListener("pointerup", onPointerUp)
window.addEventListener("pointercancel", onPointerUp)In der Entwicklungsumgebung von React führt StrictMode zu einer doppelten Komponenten-Mountierung – ein bekanntes Verhalten zur Aufdeckung von Nebenwirkungen. Ohne explizite Bereinigung der Listener vor dem erneuten Hinzufügen entstanden doppelte Event-Handler, die zu unerwünschten doppelten Auslösungen beim Loslassen von Stickers führten.
Die korrigierte Version entfernt die Listener vor dem erneuten Hinzufügen:
// Alte Handler entfernen, um Duplikate zu vermeiden
window.removeEventListener("pointermove", onPointerMove)
window.removeEventListener("pointerup", onPointerUp)
window.removeEventListener("pointercancel", onPointerUp)
// Neue Handler registrieren
window.addEventListener("pointermove", onPointerMove)
window.addEventListener("pointerup", onPointerUp)
window.addEventListener("pointercancel", onPointerUp)Diese einfache Routine vermeidet schwer zu debuggende Fehler und sorgt für eine konsistente Nutzererfahrung.
Content Security Policy: Warum Clarity und Next.js manchmal kollidieren
Die Integration von Microsoft Clarity zur Nutzeranalyse sollte durch eine Content Security Policy (CSP) abgesichert werden. Doch nach dem Hinzufügen der Header in next.config.ts funktionierte das Tracking nicht mehr. Die Ursache lag in den unterschiedlichen Subdomains, die Clarity nutzt:
- Skripte werden von
scripts.clarity.msgeladen - Tracking-Daten werden an
t.clarity.msgesendet
Ein einfacher Eintrag wie clarity.ms in der CSP reichte nicht aus – beide Subdomains mussten explizit erlaubt werden:
// script-src benötigt scripts.clarity.ms
// connect-src benötigt t.clarity.ms
// Nur clarity.ms reicht nicht ausDer Tipp aus diesem Fehler: Immer die Netzwerkanfragen im DevTools überprüfen, nachdem CSP-Header hinzugefügt wurden. Die Konsolenfehler zeigen exakt an, welche Domains blockiert werden.
Was ich beim nächsten Mal anders machen würde
Ein frühes Feature war die mehrsprachige Routenführung mit dynamischen Segmenten wie /[lang]/generator. Nach dem Entfernen der Routen blieb jedoch ein TypeScript-Fehler bestehen, weil die alten Typendefinitionen im .next/dev/types/validator.ts noch referenziert wurden. Die Lösung war einfach, aber zeitaufwendig zu debuggen: Das .next-Verzeichnis komplett löschen und einen Neubau des Projekts durchführen.
Merke: Beim Ändern von Routing-Strukturen immer den Cache bereinigen – es spart wertvolle Entwicklungszeit.
Fazit: Ein Tool, das mehr lehrt als nur Ästhetik
Der Brat-Generator steht nun als kostenloses, werbefreies Tool zur Verfügung und funktioniert auf allen Endgeräten. Für Entwickler, die Canvas-basierte Anwendungen in Next.js umsetzen, lohnt sich die Kombination aus dynamischen Importen mit reserviertem Platz und Referenzoptimierung besonders. Die Performance-Verbesserungen durch kleine Anpassungen wie den LCP-freundlichen Container waren überraschend spürbar.
Wer selbst experimentieren möchte, kann den Generator unter ibratgenerator.com testen. Gebaut mit Next.js 16, TypeScript und dem Canvas-API – und bereit für weitere Optimierungen.
KI-Zusammenfassung
Next.js 16 App Router kullanarak brat stili görsel üreticisi inşa ederken karşılaşılan performans sorunları ve SEO optimizasyonları. Detaylı teknik analiz ve çözüm önerileri.