16 - Infrastruktur & Plattform-Support¶
Dokument: PWA, Push Notifications, Multi-Plattform Stand: 28.02.2026 Scope: PWA, Service Worker, Push, Device Detection Status: Audit-ready
1. Progressive Web App (PWA)¶
1.1 Konfiguration¶
Manifest: public/manifest.json
| Parameter | Wert |
|---|---|
| Display | standalone (Vollbild) |
| Theme Color | #0d1f0d (Dunkelgrün) |
| Background | #0d1f0d |
| Orientation | any |
| Categories | games, entertainment |
1.2 Apple Web App¶
Meta-Tags (Root Layout):
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="ChainBETs" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
1.3 Viewport¶
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
| Parameter | Wert | Zweck |
|---|---|---|
| user-scalable | no | Kein Zoom |
| viewport-fit | cover | Notch-Unterstützung |
| maximum-scale | 1 | Verhindert unbeabsichtigtes Zoomen |
1.4 PWA-Installationshinweis¶
Komponente: AddToHomeScreenBanner
- Trigger: Mobile Browser, App nicht als PWA installiert
- Erkennung: useDeviceContext → isStandalone === false
- Dismiss-Button verfügbar
2. Service Worker¶
Datei: public/sw.js
2.1 Push-Event-Handler¶
self.addEventListener('push', (event) => {
const data = event.data?.json();
self.registration.showNotification(data.title || 'ChainBETs', {
body: data.body,
icon: '/icons/icon-192.png',
badge: '/favicon-96x96.png',
tag: 'chainbets-win',
renotify: true
});
});
2.2 Notification-Click-Handler¶
self.addEventListener('notificationclick', (event) => {
event.notification.close();
// Existierendes Fenster fokussieren oder neues öffnen
clients.matchAll({ type: 'window' })
.then(windowClients => {
// Focus existing or open new
});
});
3. Push-Benachrichtigungen¶
3.1 VAPID-Konfiguration¶
| Parameter | Scope | Beschreibung |
|---|---|---|
NEXT_PUBLIC_VAPID_PUBLIC_KEY |
Client | Public Key für Subscription |
VAPID_PRIVATE_KEY |
Server | Private Key für Signierung |
VAPID_SUBJECT |
Server | mailto:noreply@chainbets.win |
3.2 Push-Subscription-Library¶
Datei: lib/pushSubscription.ts
Funktionen:
| Funktion | Beschreibung |
|---|---|
isPushSupported() |
Browser-Support prüfen (SW, PushManager, Notification) |
isPwaInstalled() |
PWA-Installation prüfen |
isPushSubscribed() |
Aktive Subscription prüfen |
getRegistration() |
Service Worker registrieren (/sw.js) |
subscribeToPush(wallet) |
Push-Subscription erstellen + Backend senden |
unsubscribeFromPush(wallet) |
Subscription entfernen |
3.3 Subscription-Flow¶
1. isPushSupported() → Browser kann Push
2. getRegistration() → Service Worker registrieren
3. Notification.requestPermission() → User erlaubt Push
4. registration.pushManager.subscribe() → PushSubscription erstellen
5. POST /api/push/subscribe → Backend speichern
3.4 Subscription-Daten¶
{
"walletAddress": "0x...",
"subscription": {
"endpoint": "https://fcm.googleapis.com/...",
"p256dh": "base64...",
"auth": "base64..."
}
}
3.5 API-Endpoints¶
| Endpoint | Beschreibung |
|---|---|
POST /api/push/subscribe |
Subscription registrieren |
POST /api/push/unsubscribe |
Subscription entfernen |
DB-Tabelle: push_subscriptions
4. Multi-Plattform-Support¶
4.1 Unterstützte Plattformen¶
| Plattform | Typ | Auth | Layout |
|---|---|---|---|
| Desktop Browser | Web | Web3Auth Modal | Dashboard + Sidebar Play |
| Mobile Browser | Web | Web3Auth Modal | Fullscreen Play |
| Telegram Mobile | Mini App | Google/Apple/Email (Redirect) | Fullscreen Play |
| Telegram Desktop | Mini App | Google/Apple/Email (Popup) | Dashboard + Sidebar |
| PWA (installiert) | Standalone | Web3Auth | Fullscreen |
4.2 Device-Detection¶
Hook: useDeviceContext
| Flag | Logik |
|---|---|
isMobile |
UA-Check ODER (Touch + Width < 768px) ODER Telegram |
isDesktop |
!isMobile UND !Telegram |
isTablet |
Touch + minDim >= 480px + Width >= 1024px + !Telegram |
isTelegram |
window.Telegram.WebApp.initData vorhanden |
isIOS |
iPad/iPhone/iPod im User-Agent |
isStandalone |
display-mode: standalone ODER navigator.standalone |
4.3 Responsive Layout¶
| Breakpoint | Layout |
|---|---|
| Mobile (< 768px) | MobileFrame, Bottom-Navigation |
| Tablet (768px - 1024px) | Hybrid, Sidebar optional |
| Desktop (> 1024px) | DesktopLayout: 3-Pane (Nav + Content + Play Sidebar) |
| Desktop (> 1400px) | Erweiterte Tabellen in Global Stats |
4.4 Plattform-spezifische Features¶
| Feature | Web | Telegram | PWA |
|---|---|---|---|
| PWA-Banner | Ja | Nein | N/A |
| Push Notifications | Ja | Nein | Ja |
| Back-Button | Browser | Telegram native | Browser |
| Viewport Expansion | N/A | tgWebApp.expand() |
N/A |
| Login-Modal | Web3Auth | Direkte Buttons | Web3Auth |
| Safe Area | viewport-fit: cover | Telegram SDK | viewport-fit: cover |
5. Offline-Handling¶
5.1 Online/Offline-Erkennung¶
Hook: useOnlineStatus
| Event | State |
|---|---|
online |
isOnline = true |
offline |
isOnline = false |
| SSR | isOnline = true (Default) |
5.2 OfflineBanner¶
Komponente: app/components/OfflineBanner.tsx
- Wird automatisch bei Offline-Status angezeigt
- Verschwindet bei Reconnect
- Warning-Styling
6. Maintenance-Modus¶
6.1 Erkennung¶
Hook: useMaintenanceStatus
| Parameter | Wert |
|---|---|
| Polling | GET /api/maintenance alle 30 Sekunden |
| Response | { "maintenance": boolean } |
| Cache | 10 Sekunden |
| Fehlerfall | Annahme: kein Maintenance |
6.2 MaintenanceBanner¶
Komponente: app/components/MaintenanceBanner.tsx
- Warnung im App-Header
- Blockiert Kauf-Aktionen
- Zeigt Wartungshinweis
6.3 API-Schutz¶
Buy-Intent gibt 503 zurück wenn chain_stats.maintenance = true:
7. Confetti-Effekte (Gewinn-Animationen)¶
Datei: lib/confettiEffects.ts
7.1 Effekt-Stufen¶
| Funktion | Trigger | Beschreibung |
|---|---|---|
smallWin() |
4er Treffer | Grüner Burst, 120 Partikel, Jingle |
bigWin() |
5er Treffer | Multi-Color, 240+ Partikel, Drum Fill |
superJackpot() |
6er Treffer | Gold-Explosion, 280+ Partikel, Casino-Fanfare |
7.2 Audio-System¶
- Technologie: Web Audio API (synthetisiert, keine externen Dateien)
- Oszillatoren: Sine, Triangle, Square, Sawtooth
- Drums: Noise Bursts
- Master: DynamicsCompressor
- Persistenz:
setSound(enabled)→ localStorage - Mobile: 50% reduzierte Partikelanzahl
7.3 Steuerung¶
| Funktion | Beschreibung |
|---|---|
setSound(enabled) |
Sound an/aus (localStorage) |
isSoundOn() |
Aktueller Sound-Status |
stopAll() |
Timer und Confetti sofort stoppen |
Weiterführende Dokumente: - 01 - Systemübersicht - 09 - UI Komponenten - 11 - Telegram