📘 StimmArt Chor - Vollständige Dokumentation

📑 Inhaltsverzeichnis

  1. Projektübersicht
  2. Features
  3. Technologie-Stack
  4. Systemanforderungen
  5. Lokale Installation
  6. Konfiguration
  7. Entwicklung
  8. Produktions-Build
  9. Server-Deployment
  10. Datenbank-Management
  11. Admin-Panel Anleitung
  12. Features im Detail
  13. API-Referenz
  14. Troubleshooting
  15. Wartung & Updates

📋 Projektübersicht

StimmArt ist eine moderne Web-Anwendung für die Verwaltung und Präsentation eines Pop-Chors. Die Website bietet sowohl einen öffentlichen Bereich für Besucher als auch einen umfangreichen Admin-Bereich zur Content-Verwaltung.

Hauptziele

Projektname und Branding

Das Projekt war ursprünglich für den “Liederkranz Bieber 1847 e.V.” entwickelt und wurde 2025 zu StimmArt umgebrandet - einem modernen Pop-Chor der Singgemeinschaft Bieber/Wiesen.


✨ Features

🎯 Öffentliche Website

Hauptbereiche

Design-Features

🛠️ Admin-Panel

Content-Management

Benutzer-Management


🛠️ Technologie-Stack

Frontend

Backend

Build & Development Tools

Weitere Dependencies


💻 Systemanforderungen

Server-Anforderungen (Produktion)

Entwicklungsumgebung

Browser-Kompatibilität


📥 Lokale Installation

1. Repository klonen oder herunterladen

# Mit Git
git clone <repository-url>
cd stimmart-chor

# Oder ZIP herunterladen und entpacken
unzip Stimmart-Final.zip
cd project

2. Dependencies installieren

npm install

Dies installiert alle benötigten Pakete aus der package.json.

3. MySQL-Datenbank einrichten

Datenbank erstellen

-- In MySQL/MariaDB-Konsole
CREATE DATABASE website CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Schema importieren

# Aus dem Projekt-Verzeichnis
mysql -u root -p website < mysql-migrations/MASTER_complete_schema.sql

Hinweis: Das MASTER_complete_schema.sql enthält das komplette Schema mit allen Tabellen.

4. MySQL-Konfiguration

Erstelle die Datei mysql.conf im Projekt-Root:

HOST=localhost
PORT=3306
DATABASE=website
USERNAME=dein_mysql_benutzer
PASSWORD=dein_mysql_passwort

Wichtig: Die Datei mysql.conf sollte NICHT in Git eingecheckt werden (steht in .gitignore).

5. SMTP-Konfiguration (optional, für Kontaktformular)

Kopiere die Beispiel-Datei:

cp smtp.conf.example smtp.conf

Bearbeite smtp.conf:

HOST=smtp.gmail.com
PORT=587
SECURE=false
USERNAME=deine-email@gmail.com
PASSWORD=dein-app-passwort
FROM_EMAIL=noreply@stimmart-chor.de
FROM_NAME=StimmArt Website
TO_EMAIL=info@stimmart-chor.de

Gmail-Hinweis: Verwende ein App-Passwort, nicht dein normales Passwort.

6. Entwicklungsserver starten

npm run dev

Dies startet: - Frontend auf http://localhost:90 - Backend-API auf http://localhost:3001

7. Admin-Login

Erstelle einen Admin-Benutzer direkt in der Datenbank:

-- Passwort: "admin123" (bitte in Produktion ändern!)
INSERT INTO site_settings (id, admin_password) 
VALUES (1, 'admin123') 
ON DUPLICATE KEY UPDATE admin_password = 'admin123';

Dann öffne: http://localhost:90/admin


⚙️ Konfiguration

Umgebungsvariablen

Das Projekt verwendet primär Konfigurationsdateien (.conf), unterstützt aber auch Environment-Variablen:

# Für MySQL
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
export MYSQL_DATABASE=website
export MYSQL_USERNAME=user
export MYSQL_PASSWORD=password

# Für SMTP
export SMTP_HOST=smtp.gmail.com
export SMTP_PORT=587
export SMTP_SECURE=false
export SMTP_USERNAME=user@gmail.com
export SMTP_PASSWORD=password
export SMTP_FROM_EMAIL=noreply@domain.de
export SMTP_FROM_NAME="StimmArt"
export SMTP_TO_EMAIL=info@domain.de

# Für Node.js
export NODE_ENV=production
export PORT=3001

Ports konfigurieren

Die Ports sind in verschiedenen Dateien definiert:


🔧 Entwicklung

Verfügbare Scripts

# Development
npm run dev                    # Startet Frontend + Backend
npm run dev:frontend           # Nur Frontend
npm run dev:backend:mysql      # Nur Backend mit MySQL

# Build
npm run build                  # Frontend-Build
npm run build:server           # Backend-Build (TypeScript → JavaScript)
npm run build:all              # Frontend + Backend

# Production
npm start                      # Startet Production-Server
npm run start:mysql            # Startet MySQL-Server

# Code Quality
npm run lint                   # ESLint-Check
npm run lint:fix               # ESLint Auto-Fix
npm run format                 # Code formatieren mit Prettier
npm run format:check           # Format-Check
npm run type-check             # TypeScript-Typ-Check

# Testing
npm test                       # Tests ausführen
npm run test:ui                # Vitest UI
npm run test:coverage          # Test-Coverage

# Cleanup
npm run clean                  # Löscht dist/, dist-server/, build/

Projektstruktur

project/
├── src/
│   ├── components/              # React-Komponenten
│   │   ├── admin/              # Admin-Panel Komponenten
│   │   │   ├── AboutPage.tsx
│   │   │   ├── AdminLayout.tsx
│   │   │   ├── BieberInfoPage.tsx
│   │   │   ├── ContactFormPage.tsx
│   │   │   ├── ContactPage.tsx
│   │   │   ├── DashboardHome.tsx
│   │   │   ├── DashboardLayout.tsx
│   │   │   ├── FontsPage.tsx
│   │   │   ├── GalleryPage.tsx
│   │   │   ├── ImprintPage.tsx
│   │   │   ├── NewsPage.tsx
│   │   │   ├── PosterImagesPage.tsx
│   │   │   ├── PostersPage.tsx
│   │   │   ├── PrivacyPage.tsx
│   │   │   ├── SectionsPage.tsx
│   │   │   ├── SettingsPage.tsx
│   │   │   ├── SlideshowPage.tsx
│   │   │   ├── StimmArtPage.tsx
│   │   │   ├── VereinePage.tsx
│   │   │   ├── WiesenInfoPage.tsx
│   │   │   └── YoungStarsPage.tsx
│   │   ├── testing/            # Test-Komponenten
│   │   │   └── FontTesting.tsx
│   │   ├── AdminDashboard.tsx
│   │   ├── AdminLogin.tsx
│   │   ├── BieberFooter.tsx
│   │   ├── BieberHeader.tsx
│   │   ├── ContactFormSection.tsx
│   │   ├── CookieConsent.tsx
│   │   ├── CustomSection.tsx
│   │   ├── DynamicFontLoader.tsx
│   │   ├── ErrorBoundary.tsx
│   │   ├── Footer.tsx
│   │   ├── Header.tsx
│   │   ├── Imprint.tsx
│   │   ├── NewsSection.tsx
│   │   ├── PosterGallery.tsx
│   │   ├── PostersSection.tsx
│   │   ├── Privacy.tsx
│   │   ├── SEOHead.tsx
│   │   ├── Slideshow.tsx
│   │   ├── ThemeToggle.tsx
│   │   ├── VereineSection.tsx
│   │   ├── VoiceTypeSection.tsx
│   │   ├── WiesenFooter.tsx
│   │   ├── WiesenHeader.tsx
│   │   ├── WiesenInfo.tsx
│   │   └── YoungStarsSection.tsx
│   ├── contexts/               # React Contexts
│   │   └── ThemeContext.tsx   # Dark/Light Mode
│   ├── lib/                    # Utilities & Services
│   │   ├── analytics.ts
│   │   ├── database.types.ts
│   │   ├── db.ts              # Frontend DB API
│   │   ├── design-system.ts
│   │   ├── frontend-db.ts
│   │   ├── image-storage.ts
│   │   ├── mysql-connection.ts # MySQL-Verbindung
│   │   ├── mysql-db.ts        # MySQL-Datenbankschicht
│   │   ├── session.ts
│   │   ├── slug.ts
│   │   └── smtp-config.ts     # SMTP-Konfiguration
│   ├── server/                 # Backend
│   │   ├── middleware/
│   │   │   ├── errorHandler.ts
│   │   │   └── validation.ts
│   │   ├── routes/
│   │   │   └── mysql-api.ts   # MySQL API-Routen
│   │   ├── index.ts           # JSON-basierter Server (Legacy)
│   │   ├── index-http.ts      # HTTP-Server
│   │   ├── index-mysql.ts     # MySQL-Server (AKTUELL)
│   │   └── index-production.ts # HTTPS Production-Server
│   ├── types/                  # TypeScript-Typdefinitionen
│   │   └── ntp-client.d.ts
│   ├── App.tsx                 # Haupt-App-Komponente
│   ├── main.tsx                # React-Einstiegspunkt
│   ├── index.css               # Globale Styles
│   └── vite-env.d.ts
├── public/                     # Statische Dateien
│   ├── fonts/                  # Hochgeladene Fonts
│   └── uploads/                # Hochgeladene Bilder
│       └── general/
├── dist/                       # Frontend-Build (generiert)
├── dist-server/                # Backend-Build (generiert)
├── mysql-migrations/           # Datenbank-Migrationen
│   ├── MASTER_complete_schema.sql
│   ├── 20250112_stimmart_rebranding.sql
│   ├── 20250114_add_contact_form_field_type.sql
│   └── 20250217_add_site_settings_info_fields.sql
├── api/                        # API-Hilfsdateien
│   └── upload.ts
├── mysql.conf                  # MySQL-Konfiguration (nicht in Git)
├── smtp.conf                   # SMTP-Konfiguration (nicht in Git)
├── smtp.conf.example           # SMTP-Beispiel-Konfiguration
├── package.json
├── tsconfig.json               # TypeScript-Konfiguration
├── tsconfig.app.json           # Frontend-TypeScript-Config
├── tsconfig.server.json        # Backend-TypeScript-Config
├── vite.config.ts              # Vite-Konfiguration
├── tailwind.config.js          # Tailwind-Konfiguration
├── eslint.config.js            # ESLint-Konfiguration
├── vitest.config.ts            # Vitest-Konfiguration
└── README.md

Code-Richtlinien (aus user_rules)

  1. Eine Datei = Ein Konzept
  2. Konstruktoren nur für Initialisierung
  3. Lambdas und anonyme Klassen
  4. Statische Methoden
  5. Methoden-Länge
  6. Benennung = Bedeutung

🏗️ Produktions-Build

Build-Prozess

# 1. Frontend bauen
npm run build

# 2. Backend bauen
npm run build:server

# 3. Oder beides zusammen
npm run build:all

Was wird generiert?

Frontend (dist/)

dist/
├── index.html
├── assets/
│   ├── index-[hash].css       # Gebündeltes CSS
│   ├── index-[hash].js        # Haupt-JavaScript
│   ├── vendor-[hash].js       # Third-Party-Libraries
│   ├── router-[hash].js       # React Router
│   ├── ui-[hash].js           # UI-Komponenten
│   └── utils-[hash].js        # Utilities
├── fonts/                      # Kopierte Fonts
└── uploads/                    # Kopierte Uploads

Backend (dist-server/)

dist-server/
├── server/
│   ├── index.js
│   ├── index-mysql.js         # MySQL-Server (WICHTIG!)
│   ├── middleware/
│   │   ├── errorHandler.js
│   │   └── validation.js
│   └── routes/
│       └── mysql-api.js
└── lib/
    ├── mysql-connection.js
    ├── mysql-db.js
    └── smtp-config.js

Build-Optimierungen


🚀 Server-Deployment

Deployment-Übersicht

Basierend auf deiner Server-Installation:

Lokaler Rechner          →    Server
------------------------      ------------------------
1. Build erstellen            5. Projekt hochladen
2. Dateien komprimieren       6. Entpacken
3. ZIP hochladen              7. Dependencies installieren
4. -                          8. Build (optional)
                              9. MySQL einrichten
                              10. Services starten

Detaillierte Anleitung

Schritt 1: Lokalen Build erstellen

# Auf deinem lokalen Rechner
cd C:\Users\jonas\Desktop\project

# Build erstellen
npm run build
npm run build:server

Schritt 2: Projekt komprimieren

Erstelle eine ZIP-Datei mit folgenden Inhalten:

Erforderliche Dateien/Ordner:

Stimmart-Final.zip
├── package.json                    # WICHTIG
├── package-lock.json               # WICHTIG
├── dist/                           # Frontend-Build (optional, kann auf Server erstellt werden)
├── dist-server/                    # Backend-Build (optional)
├── src/                            # Quellcode (WICHTIG für Server-Build)
├── public/uploads/                 # Hochgeladene Bilder
├── public/fonts/                   # Hochgeladene Fonts
├── mysql-migrations/               # Datenbank-Schema
├── mysql.conf.example              # Beispiel-Konfiguration
├── smtp.conf.example               # Beispiel-Konfiguration
├── tsconfig.json                   # TypeScript-Config
├── tsconfig.server.json            # Server-TypeScript-Config
├── vite.config.ts                  # Vite-Config
└── README.md

NICHT einpacken: - node_modules/ (wird auf Server installiert) - mysql.conf (enthält Passwörter!) - smtp.conf (enthält Passwörter!) - .git/

Schritt 3: Auf Server hochladen

# Beispiel mit SCP (von lokalem Rechner)
scp Stimmart-Final.zip adminuser@server-ip:/home/adminuser/upload/

# Oder mit SFTP/FileZilla
# Hochladen nach: /home/adminuser/upload/

Schritt 4: Auf Server einloggen und entpacken

# SSH-Verbindung zum Server
ssh adminuser@server-ip

# Zum Upload-Verzeichnis wechseln
cd /home/adminuser/upload/

# ZIP entpacken
unzip Stimmart-Final.zip -d project

# In Projekt-Verzeichnis wechseln
cd project

Schritt 5: Dependencies installieren

# Node-Module installieren
npm install

# Bei Problemen: Cache leeren und neu installieren
rm -rf node_modules package-lock.json
npm install

Schritt 6: Build auf Server erstellen (wenn nicht lokal gebaut)

# Frontend-Build
npm run build

# Backend-Build
npm run build:server

Fehler beheben:

# Wenn "vite: Permission denied"
chmod +x node_modules/.bin/vite

# Oder mit sudo (wenn nötig)
sudo npm run build
sudo npm run build:server

Schritt 7: MySQL-Datenbank einrichten

# MySQL-Konsole öffnen
mysql -u root -p

# Datenbank erstellen (falls nicht vorhanden)
CREATE DATABASE website CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# Datenbank auswählen
USE website;

# Schema importieren
source /home/adminuser/upload/project/mysql-migrations/MASTER_complete_schema.sql;

# Beenden
exit;

Alternative (von Shell aus):

cd /home/adminuser/upload/project/mysql-migrations
mysql -u root -p website < MASTER_complete_schema.sql

Schritt 8: Konfigurationsdateien erstellen

cd /home/adminuser/upload/project

# MySQL-Konfiguration
nano mysql.conf

Inhalt von mysql.conf:

HOST=localhost
PORT=3306
DATABASE=website
USERNAME=dein_mysql_user
PASSWORD=dein_mysql_passwort

Speichern: Ctrl+O, Enter, Ctrl+X

# SMTP-Konfiguration (optional)
nano smtp.conf

Inhalt von smtp.conf:

HOST=smtp.gmail.com
PORT=587
SECURE=false
USERNAME=deine-email@gmail.com
PASSWORD=dein-app-passwort
FROM_EMAIL=noreply@stimmart-chor.de
FROM_NAME=StimmArt Website
TO_EMAIL=info@stimmart-chor.de

Schritt 9: Projekt nach /var/www/ kopieren

# Root-Rechte
sudo su

# Altes Projekt sichern/entfernen
cd /var/www/Stimmart
rm -rf project/ dist/

# Neues Projekt kopieren
cp -r /home/adminuser/upload/project /var/www/Stimmart/

# dist/ Ordner separat kopieren (für Apache)
cp -r /var/www/Stimmart/project/dist /var/www/Stimmart/

# Berechtigungen setzen
chown -R www-data:www-data /var/www/Stimmart/
chmod -R 755 /var/www/Stimmart/

# Upload-Ordner beschreibbar machen
chmod -R 775 /var/www/Stimmart/project/public/uploads/
chmod -R 775 /var/www/Stimmart/project/public/fonts/

Schritt 10: Systemd-Service einrichten

Erstelle die Datei /etc/systemd/system/stimmart-api.service:

sudo nano /etc/systemd/system/stimmart-api.service

Inhalt:

[Unit]
Description=StimmArt Chor API Server
After=network.target mysql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/Stimmart/project
ExecStart=/usr/bin/npm exec tsx src/server/index-mysql.ts
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Service aktivieren:

# Service neu laden
sudo systemctl daemon-reload

# Service aktivieren (automatischer Start beim Booten)
sudo systemctl enable stimmart-api.service

# Service starten
sudo systemctl start stimmart-api.service

# Status prüfen
sudo systemctl status stimmart-api.service

Schritt 11: Apache konfigurieren

Erstelle eine Virtual Host-Datei:

sudo nano /etc/apache2/sites-available/stimmart.conf

Inhalt:

<VirtualHost *:80>
    ServerName stimmart-chor.de
    ServerAlias www.stimmart-chor.de

    DocumentRoot /var/www/Stimmart/dist

    # Frontend (statische Dateien)
    <Directory /var/www/Stimmart/dist>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted

        # React Router Support
        RewriteEngine On
        RewriteBase /
        RewriteRule ^index\.html$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.html [L]
    </Directory>

    # API-Proxy zu Node.js-Backend
    ProxyPreserveHost On
    ProxyPass /api http://localhost:3001/api
    ProxyPassReverse /api http://localhost:3001/api
    ProxyPass /health http://localhost:3001/health
    ProxyPassReverse /health http://localhost:3001/health

    # Uploads und Fonts
    Alias /uploads /var/www/Stimmart/project/public/uploads
    Alias /fonts /var/www/Stimmart/project/public/fonts

    <Directory /var/www/Stimmart/project/public/uploads>
        Options -Indexes
        Require all granted
    </Directory>

    <Directory /var/www/Stimmart/project/public/fonts>
        Options -Indexes
        Require all granted
    </Directory>

    # Logs
    ErrorLog ${APACHE_LOG_DIR}/stimmart_error.log
    CustomLog ${APACHE_LOG_DIR}/stimmart_access.log combined
</VirtualHost>

Apache-Module aktivieren und Site aktivieren:

# Erforderliche Module
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod rewrite

# Site aktivieren
sudo a2ensite stimmart.conf

# Apache neu laden
sudo systemctl reload apache2

Schritt 12: Services starten

# API-Service starten
sudo systemctl start stimmart-api.service

# Apache starten
sudo systemctl start apache2

# Status prüfen
sudo systemctl status stimmart-api.service
sudo systemctl status apache2

Schritt 13: Testen

# API-Health-Check
curl http://localhost:3001/health

# Website öffnen
# Im Browser: http://deine-server-ip

Server-Wartung

Logs ansehen

# API-Logs
sudo journalctl -u stimmart-api.service -f

# Apache-Logs
sudo tail -f /var/log/apache2/stimmart_error.log
sudo tail -f /var/log/apache2/stimmart_access.log

Services neustarten

# Nach Code-Änderungen
sudo systemctl restart stimmart-api.service
sudo systemctl reload apache2

Backups erstellen

# Datenbank-Backup
mysqldump -u root -p website > backup_$(date +%Y%m%d).sql

# Dateien-Backup
tar -czf backup_files_$(date +%Y%m%d).tar.gz /var/www/Stimmart/project/public/uploads/

🗄️ Datenbank-Management

Datenbank-Schema

Die Datenbank enthält folgende Tabellen:

1. site_settings

CREATE TABLE site_settings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    site_title VARCHAR(255),
    site_description TEXT,
    about_title VARCHAR(255),
    about_description TEXT,
    about_youtube_url VARCHAR(500),
    header_logo_url VARCHAR(500),
    admin_password VARCHAR(255),
    youngstars_enabled BOOLEAN DEFAULT false,
    youngstars_title VARCHAR(255),
    youngstars_description TEXT,
    youngstars_logo_url VARCHAR(500),
    -- ... weitere Felder
);

2. news

CREATE TABLE news (
    id VARCHAR(36) PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    excerpt TEXT,
    date DATE,
    image_url VARCHAR(500),
    category VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

3. slides

CREATE TABLE slides (
    id VARCHAR(36) PRIMARY KEY,
    image_url VARCHAR(500) NOT NULL,
    caption TEXT,
    display_order INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE gallery (
    id VARCHAR(36) PRIMARY KEY,
    image_url VARCHAR(500) NOT NULL,
    category VARCHAR(100),
    caption TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

5. posters

CREATE TABLE posters (
    id VARCHAR(36) PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    event_date DATE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

6. poster_images

CREATE TABLE poster_images (
    id VARCHAR(36) PRIMARY KEY,
    poster_id VARCHAR(36),
    image_url VARCHAR(500) NOT NULL,
    display_order INT DEFAULT 0,
    FOREIGN KEY (poster_id) REFERENCES posters(id) ON DELETE CASCADE
);

7. fonts

CREATE TABLE fonts (
    id VARCHAR(36) PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    family_name VARCHAR(255),
    uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

8. font_files

CREATE TABLE font_files (
    id VARCHAR(36) PRIMARY KEY,
    font_id VARCHAR(36),
    file_path VARCHAR(500) NOT NULL,
    format VARCHAR(50),
    FOREIGN KEY (font_id) REFERENCES fonts(id) ON DELETE CASCADE
);

9. custom_sections

CREATE TABLE custom_sections (
    id VARCHAR(36) PRIMARY KEY,
    title VARCHAR(255),
    content TEXT,
    display_order INT DEFAULT 0,
    is_active BOOLEAN DEFAULT true,
    background_color VARCHAR(50),
    text_color VARCHAR(50),
    font_family VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

10. contact_form_settings

CREATE TABLE contact_form_settings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    enabled BOOLEAN DEFAULT false,
    title VARCHAR(255),
    description TEXT,
    -- ... viele weitere Felder für Texte und Styling
);

11. contact_form_requests

CREATE TABLE contact_form_requests (
    id VARCHAR(36) PRIMARY KEY,
    request_number VARCHAR(20) UNIQUE,
    name VARCHAR(255),
    email VARCHAR(255),
    phone VARCHAR(50),
    message TEXT,
    submitted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    email_sent BOOLEAN DEFAULT false
);

Migrationen ausführen

# Komplettes Schema neu erstellen
mysql -u root -p website < mysql-migrations/MASTER_complete_schema.sql

# Einzelne Migration
mysql -u root -p website < mysql-migrations/20250112_stimmart_rebranding.sql

Datenbank-Backups

Backup erstellen

# Komplettes Backup
mysqldump -u root -p website > backup_website_$(date +%Y%m%d_%H%M%S).sql

# Nur Struktur (ohne Daten)
mysqldump -u root -p --no-data website > schema_only.sql

# Nur Daten (ohne Struktur)
mysqldump -u root -p --no-create-info website > data_only.sql

Backup wiederherstellen

mysql -u root -p website < backup_website_20251014_120000.sql

Datenbank-Wartung

-- Tabellengrößen anzeigen
SELECT 
    table_name AS 'Tabelle',
    ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Größe (MB)'
FROM information_schema.TABLES 
WHERE table_schema = 'website'
ORDER BY (data_length + index_length) DESC;

-- Anzahl Einträge pro Tabelle
SELECT 
    table_name AS 'Tabelle',
    table_rows AS 'Anzahl Zeilen'
FROM information_schema.TABLES 
WHERE table_schema = 'website';

-- Tabellen optimieren
OPTIMIZE TABLE news, slides, gallery, posters;

👨‍💼 Admin-Panel Anleitung

Login

  1. Öffne: https://deine-domain.de/admin oder http://localhost:90/admin
  2. Gib das Admin-Passwort ein
  3. Klicke auf “Anmelden”

Standard-Passwort ändern:

-- In MySQL
UPDATE site_settings SET admin_password = 'dein_neues_passwort' WHERE id = 1;

Dashboard-Übersicht

Nach dem Login siehst du das Dashboard mit folgenden Bereichen:

┌─────────────────────────────────────────┐
│         Dashboard                        │
├─────────────────────────────────────────┤
│ □ Dashboard                              │
│ □ Website-Einstellungen                  │
│ □ Slideshow                              │
│ □ News                                   │
│ □ Galerie                                │
│ □ Plakate                                │
│ □ Plakat-Bilder                          │
│ □ Stimmarten                             │
│ □ YoungStars                             │
│ □ Vereine                                │
│ □ Kontaktformular                        │
│ □ Custom Sections                        │
│ □ Schriftarten                           │
│ □ Über uns                               │
│ □ Kontakt                                │
│ □ Impressum                              │
│ □ Datenschutz                            │
└─────────────────────────────────────────┘

Bereiche im Detail

1. Website-Einstellungen

Allgemein: - Seitentitel: Browser-Tab-Titel (z.B. “StimmArt - Pop-Chor”) - Seitenbeschreibung: Meta-Description für Suchmaschinen

Header-Logo: 1. Klicke auf “Bild hochladen” 2. Wähle dein Logo (empfohlen: PNG mit transparentem Hintergrund, Höhe ca. 60px) 3. Logo wird automatisch im Header angezeigt

YouTube-Video: 1. Gib die YouTube-URL ein: https://www.youtube.com/watch?v=VIDEO_ID 2. Das Video erscheint in der “Das sind wir!”-Sektion

Farben & Styling: - Primärfarbe, Sekundärfarbe, Akzentfarbe - Dark Mode automatisch angepasst

2. Slideshow

Bilder verwalten: 1. Klicke auf “Bilder hochladen” 2. Wähle ein oder mehrere Bilder (JPG, PNG) 3. Optional: Bildunterschrift hinzufügen 4. Reihenfolge ändern: Ziehe Bilder per Drag & Drop 5. Löschen: Klicke auf das Papierkorb-Icon

Tipps: - Empfohlene Größe: 1920x1080px (Full HD) - Format: JPG für Fotos, PNG für Grafiken - Dateigröße: Max. 5 MB pro Bild

3. News

Artikel erstellen: 1. Klicke auf “Neuer Artikel” 2. Titel: Überschrift des Artikels 3. Kategorie: z.B. “Konzert”, “Probe”, “Allgemein” 4. Datum: Veröffentlichungsdatum 5. Kurzbeschreibung: Teaser-Text (2-3 Sätze) 6. Inhalt: Vollständiger Artikel-Text 7. Bild hochladen: Optional 8. Klicke auf “Speichern”

Artikel bearbeiten: - Klicke in der Liste auf den Stift-Button - Ändere die Felder - Speichern

Artikel löschen: - Klicke auf das Papierkorb-Icon - Bestätige die Löschung

4. Galerie

Bilder hochladen: 1. Klicke auf “Bilder hochladen” 2. Mehrfach-Auswahl möglich! 3. Wähle eine Kategorie (z.B. “Konzert 2024”, “Proben”, “Ausflug”) 4. Optional: Bildunterschrift pro Bild 5. Hochladen

Kategorien verwenden: - Kategorien helfen bei der Organisation - Besucher können nach Kategorie filtern - Kategorien werden automatisch erstellt

5. Plakate

Plakat-Event erstellen: 1. Klicke auf “Neues Plakat” 2. Titel: Name des Events (z.B. “Frühjahrskonzert 2025”) 3. Beschreibung: Details zum Event 4. Datum: Event-Datum 5. Speichern

Bilder zum Plakat hinzufügen: 1. Gehe zu Plakat-Bilder 2. Wähle das Event aus dem Dropdown 3. Lade ein oder mehrere Plakat-Bilder hoch 4. Reihenfolge per Drag & Drop anpassen

6. Stimmarten

Für jede Stimme (Sopran, Alt, Tenor, Bass):

  1. Wähle die Stimme aus
  2. Titel: z.B. “Sopran - Die hohen Stimmen”
  3. Beschreibung: Text über diese Stimmgruppe
  4. Bild hochladen: Foto der Sänger
  5. Speichern

7. YoungStars

Aktivierung: 1. Toggle “YoungStars-Sektion aktivieren” auf AN 2. Die Sektion erscheint auf der Website

Konfiguration: 1. Titel: z.B. “StimmArt YoungStars” 2. Logo hochladen: Logo für den Jugendchor (optional) 3. Beschreibung: Text über den Jugendchor 4. Galerie: Bilder hochladen (Mehrfachauswahl möglich) 5. Speichern

Deaktivierung: - Toggle ausschalten → Sektion verschwindet von der Website - Daten bleiben gespeichert!

8. Kontaktformular

Tab 1: Aktivierung - Toggle “Kontaktformular aktivieren” auf AN

Tab 2: Inhalte Hier kannst du ALLE Texte anpassen: - Sektions-Titel (z.B. “Kontaktieren Sie uns!”) - Beschreibung - Feld-Labels (Name, E-Mail, Telefon, Nachricht) - Button-Text (“Absenden”) - Erfolgs- und Fehlermeldungen - Datenschutz-Checkbox-Text

Tab 3: Styling - Hintergrundfarbe (transparent = durchsichtig) - Textfarbe (inherit = erbt von Theme) - Button-Farben - Border-Farbe

Tipp: Lass Farben auf “transparent” oder “inherit” für automatische Dark/Light Mode-Anpassung!

Tab 4: Anfragen Hier siehst du alle eingegangenen Anfragen: - Anfrage-ID: Eindeutige Nummer (#00001, #00002, …) - Name, E-Mail, Telefon - Nachricht - Datum/Uhrzeit - E-Mail versendet? Ja/Nein

Du kannst Anfragen durchsuchen und exportieren.

9. Custom Sections

Neue Sektion erstellen: 1. Klicke auf “Neue Sektion” 2. Titel: Überschrift der Sektion 3. Inhalt: Rich-Text mit Formatierung - Fett, Kursiv, Unterstrichen - Listen (nummeriert, Bullet-Points) - Links - Bilder einfügen 4. Styling: - Hintergrundfarbe - Textfarbe - Schriftart (aus hochgeladenen Fonts wählen) 5. Reihenfolge: Ziffer eingeben (niedrigere Zahl = weiter oben) 6. Aktiv/Inaktiv: Toggle zum Ein-/Ausblenden 7. Speichern

Sektion bearbeiten: - Klicke auf “Bearbeiten” - Ändere Felder - Speichern

Reihenfolge ändern: - Per Drag & Drop - Oder Zahl in “Display Order” ändern

10. Schriftarten

Font hochladen: 1. Klicke auf “Schriftart hochladen” 2. Name: Display-Name (z.B. “Cavolini”) 3. Familie: Font-Family-Name (z.B. “Cavolini”) 4. Dateien auswählen: - TTF (TrueType) - OTF (OpenType) - WOFF (Web Open Font Format) - WOFF2 (beste Browser-Unterstützung!) 5. Mehrere Formate hochladen (empfohlen für beste Kompatibilität) 6. Hochladen

Font-Vorschau: - Automatische Vorschau mit Demo-Text - Teste verschiedene Größen

Font verwenden: - In Custom Sections: Dropdown-Auswahl - In Website-Einstellungen für globale Nutzung

Font löschen: - Klicke auf Papierkorb - Achtung: Wird auch aus allen Sektionen entfernt!

11. Über uns / Kontakt / Impressum / Datenschutz

Diese Bereiche haben ein einheitliches Interface:

  1. Rich-Text-Editor für Inhalt
  2. Vorschau in Echtzeit
  3. Speichern-Button

Impressum & Datenschutz: - Rechtliche Pflichtangaben - Automatisch verlinkt im Footer - Eigene Seiten (/imprint, /privacy)


🔍 Features im Detail

1. Dark/Light Mode

Automatische Erkennung: - System-Präferenz wird erkannt (prefers-color-scheme) - Beim ersten Besuch: System-Einstellung übernommen

Manueller Toggle: - Button in der Navigation - Wahl wird in localStorage gespeichert - Bleibt über Seitenaufrufe hinweg erhalten

Für Entwickler:

// ThemeContext verwenden
import { useTheme } from '@/contexts/ThemeContext';

function MyComponent() {
  const { theme, toggleTheme } = useTheme();
  
  return (
    <div className={theme === 'dark' ? 'bg-gray-900' : 'bg-white'}>
      <button onClick={toggleTheme}>Toggle</button>
    </div>
  );
}

2. Custom Fonts

Workflow: 1. Designer erstellt Font 2. Admin lädt Font hoch (.woff2 empfohlen) 3. System generiert @font-face CSS 4. Font ist in Custom Sections verfügbar

Technische Details: - Fonts werden in /public/fonts/[font-id]/ gespeichert - Automatische CSS-Generierung in DynamicFontLoader.tsx - Dynamisches Nachladen beim Seitenwechsel

Font-Format-Priorität: 1. WOFF2 (beste Kompression, moderne Browser) 2. WOFF (gute Kompatibilität) 3. TTF/OTF (Fallback für alte Browser)

3. Kontaktformular mit SMTP

Ablauf: 1. Besucher füllt Formular aus 2. Frontend sendet Daten an /api/contact-form 3. Backend: - Validiert Eingaben - Speichert in Datenbank mit eindeutiger ID - Versucht E-Mail zu versenden 4. Erfolg- oder Fehlermeldung

E-Mail-Vorlage:

Betreff: Neue Kontaktanfrage von [Name]

Neue Kontaktanfrage über das Website-Formular:

Anfrage-ID: #00042
Name: Max Mustermann
E-Mail: max@example.com
Telefon: 0123/456789

Nachricht:
Hallo, ich interessiere mich für...

---
Diese E-Mail wurde automatisch über das Kontaktformular auf stimmart-chor.de gesendet.

Fehlerbehandlung: - SMTP-Fehler → Anfrage wird trotzdem gespeichert - Admin kann Anfragen im Panel einsehen - Log-Eintrag im Server-Log

4. SEO-Optimierung

Meta-Tags:

<head>
  <title>StimmArt - Pop-Chor Singgemeinschaft Bieber/Wiesen</title>
  <meta name="description" content="...">
  <meta name="keywords" content="Pop-Chor, StimmArt, ...">
  
  <!-- Open Graph (Facebook, WhatsApp) -->
  <meta property="og:title" content="StimmArt">
  <meta property="og:description" content="...">
  <meta property="og:image" content="...">
  <meta property="og:url" content="https://stimmart-chor.de">
  
  <!-- Twitter Card -->
  <meta name="twitter:card" content="summary_large_image">
  
  <!-- Canonical URL -->
  <link rel="canonical" href="https://stimmart-chor.de">
</head>

Strukturierte Daten:

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "StimmArt",
  "description": "Pop-Chor...",
  "url": "https://stimmart-chor.de"
}

Best Practices: - Sprechende URLs - Alt-Texte für Bilder - Semantisches HTML (<header>, <nav>, <main>, <footer>) - Performance-Optimierung (Lighthouse Score > 90)

5. Drag & Drop

Verwendung: - Slideshow: Bilder sortieren - Plakat-Bilder: Reihenfolge festlegen - Custom Sections: Sortierung

Technologie: - @dnd-kit/core - @dnd-kit/sortable - Touch-Support für Mobile

Code-Beispiel:

import { DndContext, closestCenter } from '@dnd-kit/core';
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';

<DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
  <SortableContext items={items} strategy={verticalListSortingStrategy}>
    {items.map(item => <SortableItem key={item.id} item={item} />)}
  </SortableContext>
</DndContext>

📡 API-Referenz

Base URL

Endpoints

News

GET /api/news

// Alle News abrufen
fetch('/api/news')
  .then(res => res.json())
  .then(data => console.log(data));

// Response
[
  {
    "id": "uuid-here",
    "title": "Konzert am 15. März",
    "content": "...",
    "excerpt": "...",
    "date": "2025-03-15",
    "image_url": "/uploads/general/concert.jpg",
    "category": "Konzert",
    "created_at": "2025-01-10T12:00:00Z",
    "updated_at": "2025-01-10T12:00:00Z"
  }
]

GET /api/news/:id

// Einzelnen Artikel abrufen
fetch('/api/news/uuid-here')

POST /api/news

// Neuen Artikel erstellen (Admin)
fetch('/api/news', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    title: "Neuer Artikel",
    content: "...",
    date: "2025-03-15",
    category: "Konzert"
  })
})

PUT /api/news/:id

// Artikel aktualisieren
fetch('/api/news/uuid-here', {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ title: "Geänderter Titel" })
})

DELETE /api/news/:id

// Artikel löschen
fetch('/api/news/uuid-here', { method: 'DELETE' })

Slideshow

GET /api/slides POST /api/slides DELETE /api/slides/:id PUT /api/slides/reorder - Reihenfolge ändern

Galerie

GET /api/gallery POST /api/gallery DELETE /api/gallery/:id

Site Settings

GET /api/settings

// Website-Einstellungen abrufen
fetch('/api/settings')
  .then(res => res.json())
  .then(settings => {
    console.log(settings.site_title);
    console.log(settings.header_logo_url);
    console.log(settings.about_youtube_url);
  });

PUT /api/settings

Kontaktformular

GET /api/contact-form/settings PUT /api/contact-form/settings

POST /api/contact-form

// Kontaktanfrage senden
fetch('/api/contact-form', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: "Max Mustermann",
    email: "max@example.com",
    phone: "0123/456789",
    message: "Hallo, ich interessiere mich..."
  })
})

GET /api/contact-form/requests

// Alle Anfragen abrufen (Admin)
fetch('/api/contact-form/requests')
  .then(res => res.json())
  .then(requests => {
    requests.forEach(req => {
      console.log(req.request_number); // #00001
      console.log(req.name);
      console.log(req.email);
      console.log(req.message);
      console.log(req.email_sent); // true/false
    });
  });

Uploads

POST /api/upload

// Bild hochladen
const formData = new FormData();
formData.append('image', fileInput.files[0]);
formData.append('category', 'general');

fetch('/api/upload', {
  method: 'POST',
  body: formData
})
.then(res => res.json())
.then(data => {
  console.log('Bild-URL:', data.url);
  // z.B. "/uploads/general/1760445086693-7aad5049.png"
});

Fonts

GET /api/fonts POST /api/fonts/upload DELETE /api/fonts/:id

Health Check

GET /health

// Server-Status prüfen
fetch('/health')
  .then(res => res.json())
  .then(data => {
    console.log(data.status); // "healthy"
    console.log(data.database); // "connected"
    console.log(data.timestamp);
  });

GET /api/db-status

// Datenbankstatus
fetch('/api/db-status')
  .then(res => res.json())
  .then(data => {
    console.log(data.connected); // true/false
    console.log(data.tables); // Liste aller Tabellen
  });

🔧 Troubleshooting

Häufige Probleme

1. npm install schlägt fehl

Problem:

npm ERR! code EACCES
npm ERR! syscall access

Lösung:

# Berechtigungen reparieren
sudo chown -R $(whoami) ~/.npm
sudo chown -R $(whoami) node_modules

# Oder mit sudo (nicht empfohlen)
sudo npm install

2. Build-Fehler: “vite: Permission denied”

Problem:

sh: 1: vite: Permission denied

Lösung:

# Ausführungsrechte setzen
chmod +x node_modules/.bin/vite

# Oder node_modules neu installieren
rm -rf node_modules package-lock.json
npm install

3. MySQL-Verbindungsfehler

Problem:

Error: connect ECONNREFUSED 127.0.0.1:3306

Lösungen:

a) MySQL läuft nicht:

# MySQL starten
sudo systemctl start mysql

# Status prüfen
sudo systemctl status mysql

b) Falsche Zugangsdaten:

# mysql.conf überprüfen
cat mysql.conf

# Zugangsdaten testen
mysql -u USERNAME -p DATABASE

c) MySQL hört nur auf localhost:

# In /etc/mysql/mariadb.conf.d/50-server.cnf
bind-address = 127.0.0.1

# MySQL neustarten
sudo systemctl restart mysql

4. Port 3001 bereits belegt

Problem:

Error: listen EADDRINUSE: address already in use :::3001

Lösung:

# Prozess finden
lsof -i :3001

# Prozess beenden
kill -9 <PID>

# Oder anderen Port in src/server/index-mysql.ts verwenden
const PORT = process.env.PORT || 3002;

5. Uploads funktionieren nicht

Problem: Bilder werden nicht hochgeladen oder angezeigt.

Lösungen:

a) Berechtigungen:

# Upload-Ordner beschreibbar machen
sudo chmod -R 775 /var/www/Stimmart/project/public/uploads/
sudo chown -R www-data:www-data /var/www/Stimmart/project/public/uploads/

b) Apache-Konfiguration:

# In /etc/apache2/sites-available/stimmart.conf
Alias /uploads /var/www/Stimmart/project/public/uploads

<Directory /var/www/Stimmart/project/public/uploads>
    Options -Indexes
    Require all granted
</Directory>

c) Maximale Upload-Größe:

# In php.ini (falls PHP verwendet wird)
upload_max_filesize = 20M
post_max_size = 20M

6. SMTP-E-Mails kommen nicht an

Problem: Kontaktformular-E-Mails werden nicht versendet.

Lösungen:

a) SMTP-Konfiguration prüfen:

cat smtp.conf

b) Firewall-Regel für Port 587:

# Port 587 testen
telnet smtp.gmail.com 587

# Firewall öffnen (Ubuntu)
sudo ufw allow 587/tcp

c) Gmail App-Passwort: - Normale Gmail-Passwörter funktionieren nicht - Erstelle ein App-Passwort: 1. Google-Konto → Sicherheit 2. 2-Faktor-Authentifizierung aktivieren 3. App-Passwörter generieren 4. Passwort in smtp.conf eintragen

d) Server-Logs prüfen:

# API-Logs ansehen
sudo journalctl -u stimmart-api.service -f

# Nach SMTP-Fehlern suchen
sudo journalctl -u stimmart-api.service | grep SMTP

7. React Router funktioniert nicht (404 auf Refresh)

Problem: Direkter Aufruf von /admin oder /imprint gibt 404.

Lösung: Apache Rewrite-Rules

# In /etc/apache2/sites-available/stimmart.conf
<Directory /var/www/Stimmart/dist>
    Options -Indexes +FollowSymLinks
    AllowOverride All
    Require all granted

    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
</Directory>
# mod_rewrite aktivieren
sudo a2enmod rewrite
sudo systemctl reload apache2

8. Dark Mode funktioniert nicht

Problem: Theme wechselt nicht oder bleibt hängen.

Lösungen:

a) localStorage leeren:

// In Browser-Konsole
localStorage.removeItem('theme');
location.reload();

b) ThemeContext prüfen:

# Stelle sicher, dass App.tsx ThemeProvider verwendet
grep -n "ThemeProvider" src/App.tsx

9. Fonts werden nicht geladen

Problem: Custom Fonts erscheinen nicht auf der Website.

Lösungen:

a) Font-Dateien überprüfen:

# Existieren die Font-Dateien?
ls -la /var/www/Stimmart/project/public/fonts/

# Berechtigungen
sudo chmod -R 755 /var/www/Stimmart/project/public/fonts/

b) Browser-Cache leeren: - Strg+Shift+R (Hard Reload) - Browser-DevTools → Network → “Disable cache”

c) @font-face CSS prüfen:

// In Browser-Konsole
console.log(document.styleSheets);

10. Performance-Probleme

Problem: Website lädt langsam.

Lösungen:

a) Bildgrößen reduzieren:

# ImageMagick installieren
sudo apt install imagemagick

# Bilder optimieren
mogrify -resize 1920x1080 -quality 85 *.jpg

b) Browser-Caching aktivieren:

# In /etc/apache2/sites-available/stimmart.conf
<Directory /var/www/Stimmart/dist>
    # Browser-Caching
    <FilesMatch "\.(jpg|jpeg|png|gif|webp|css|js|woff|woff2)$">
        Header set Cache-Control "max-age=31536000, public"
    </FilesMatch>
</Directory>

c) Gzip-Kompression:

# mod_deflate aktivieren
sudo a2enmod deflate

# In Apache-Config
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
</IfModule>

🔄 Wartung & Updates

Regelmäßige Wartung

Wöchentlich

Monatlich

Jährlich

Updates einspielen

Code-Update

# Auf lokalem Rechner
git pull origin main
npm install
npm run build:all

# ZIP erstellen und auf Server hochladen
# Dann auf Server:
cd /var/www/Stimmart
sudo systemctl stop stimmart-api.service
cp -r /home/adminuser/upload/project/ .
cd project
npm install
npm run build:all
sudo systemctl start stimmart-api.service

Datenbank-Migration

# Neue Migration ausführen
mysql -u root -p website < mysql-migrations/NEW_MIGRATION.sql

# Service neustarten
sudo systemctl restart stimmart-api.service

Dependency-Updates

# Veraltete Pakete anzeigen
npm outdated

# Alle Minor/Patch-Updates
npm update

# Major-Update (vorsichtig!)
npm install package-name@latest

# Testen!
npm run dev
npm test

Monitoring

Server-Status überwachen

# Systemd-Service-Status
sudo systemctl status stimmart-api.service
sudo systemctl status apache2
sudo systemctl status mysql

# Ressourcen-Nutzung
htop
df -h  # Speicherplatz
free -h  # RAM

# Logs in Echtzeit
sudo journalctl -u stimmart-api.service -f
sudo tail -f /var/log/apache2/stimmart_error.log

Automatische Health-Checks

Erstelle ein Cronjob:

sudo crontab -e

Füge hinzu:

# Jede 5 Minuten: Health-Check
*/5 * * * * curl -s http://localhost:3001/health > /dev/null || systemctl restart stimmart-api.service

# Täglich um 2 Uhr: Datenbank-Backup
0 2 * * * mysqldump -u root -pPASSWORD website > /var/backups/website_$(date +\%Y\%m\%d).sql

Backup-Strategie

Automatisches Backup-Script

Erstelle /usr/local/bin/backup-stimmart.sh:

#!/bin/bash
BACKUP_DIR="/var/backups/stimmart"
DATE=$(date +%Y%m%d_%H%M%S)

# Verzeichnis erstellen
mkdir -p $BACKUP_DIR

# Datenbank-Backup
mysqldump -u root -p$(cat /root/.mysql_password) website > $BACKUP_DIR/db_$DATE.sql

# Dateien-Backup
tar -czf $BACKUP_DIR/files_$DATE.tar.gz /var/www/Stimmart/project/public/uploads /var/www/Stimmart/project/public/fonts

# Alte Backups löschen (älter als 30 Tage)
find $BACKUP_DIR -type f -mtime +30 -delete

echo "Backup abgeschlossen: $DATE"

Ausführbar machen und testen:

sudo chmod +x /usr/local/bin/backup-stimmart.sh
sudo /usr/local/bin/backup-stimmart.sh

Cronjob hinzufügen:

# Täglich um 2:30 Uhr
30 2 * * * /usr/local/bin/backup-stimmart.sh >> /var/log/backup.log 2>&1

📞 Support & Kontakt

Dokumentation

Logs & Debugging

# API-Server-Logs
sudo journalctl -u stimmart-api.service -n 100

# Apache-Error-Log
sudo tail -n 100 /var/log/apache2/stimmart_error.log

# MySQL-Logs
sudo tail -n 100 /var/log/mysql/error.log

# Node.js im Debug-Modus
NODE_ENV=development DEBUG=* npm start

Entwickler-Tools

Hilfreiche Befehle

# Projekt-Info
npm list --depth=0          # Installierte Pakete
npm run                     # Verfügbare Scripts
node -v                     # Node.js-Version
mysql --version             # MySQL-Version

# Git-Status
git status
git log --oneline -10

# Systeminfo
uname -a                    # Linux-Version
lsb_release -a              # Ubuntu-Version
systemctl list-units --type=service --state=running  # Laufende Services

Entwickelt für: StimmArt - Pop-Chor Singgemeinschaft Bieber/Wiesen
Original: Liederkranz Bieber 1847 e.V.
Rebranding: Januar 2025


✅ Checkliste: Von Null bis Deploy

Lokale Entwicklung

Produktion

Nach Deployment


🎉 Herzlichen Glückwunsch! Deine StimmArt-Website läuft!

Bei Fragen oder Problemen: Sieh dir das Troubleshooting-Kapitel an oder erstelle ein Issue im Repository.