Diese Anleitung erklaert Schritt fuer Schritt, wie du eine eigene Instanz von malziME auf deinem eigenen Firebase-Projekt betreibst — mit deiner eigenen Domain und deiner eigenen Abrechnung.
Zeitaufwand: ca. 30–60 Minuten (je nach Google Cloud Erfahrung).
- Node.js 24+
- Firebase CLI:
npm i -g firebase-tools - Ein Google-Konto mit Kreditkarte (fuer Google Cloud Abrechnung)
- Git
# Fork auf GitHub erstellen, dann:
git clone https://github.com/DEIN-USERNAME/malzime.git
cd malzime- Gehe zu console.cloud.google.com
- Erstelle ein neues Projekt (z.B.
mein-malzime) - Aktiviere die Abrechnung fuer das Projekt
Im Google Cloud Console unter APIs & Services > Library diese beiden APIs aktivieren:
- Cloud Vision API — fuer Texterkennung und Label-Erkennung
- Vertex AI API — fuer Gemini (Bildbeschreibung + Profilgenerierung)
- Cloud Firestore — fuer den Analyse-Zaehler und das Stundenlimit (wird automatisch mit Firebase aktiviert)
Wichtig: Die EU Vision API (
eu-vision.googleapis.com) unterstuetzt nurTEXT_DETECTIONundLABEL_DETECTION. Andere Features wieFACE_DETECTIONoderOBJECT_LOCALIZATIONwuerden den gesamten API-Call crashen.
- Gehe zu console.firebase.google.com
- Klicke auf Projekt hinzufuegen
- Waehle das Google Cloud Projekt aus Schritt 2 (Firebase verknuepft sich damit)
- Hosting aktivieren (unter Build > Hosting)
firebase login
firebase use --add # Deine neue Projekt-ID waehlen# Backend
cd functions && npm install && cd ..
# Frontend-Tests + Linting
npm installHier sind alle Stellen die du fuer deine eigene Instanz anpassen musst.
Datei: functions/src/domains.js
Alle erlaubten Domains sind zentral in einer Datei definiert. Ersetze sie mit deinen eigenen:
const ALLOWED_ORIGINS = [
"https://DEINE-DOMAIN.com",
"https://www.DEINE-DOMAIN.com",
"https://DEIN-PROJEKT.web.app",
"https://DEIN-PROJEKT.firebaseapp.com",
];
module.exports = { ALLOWED_ORIGINS };Falls du keine eigene Domain hast, reichen die Firebase-Defaults:
const ALLOWED_ORIGINS = [
"https://DEIN-PROJEKT.web.app",
"https://DEIN-PROJEKT.firebaseapp.com",
];Datei: functions/src/gemini.js (Zeile 83)
// Vorher:
const project = process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT || "malzime";
// Nachher — deine Projekt-ID:
const project = process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT || "DEIN-PROJEKT";Normalerweise wird die Projekt-ID automatisch erkannt. Der Fallback greift nur in seltenen Faellen.
Datei: public/js/geocoding.js (Zeile 17)
Im Code steht ein User-Agent-Header fuer Nominatim (OpenStreetMap Geocoding). Wichtig: Browser ignorieren diesen Header stillschweigend — er hat keinen Effekt. Nominatim verwendet stattdessen den Standard-User-Agent deines Browsers, was fuer die Nutzung ausreichend ist.
Du kannst den Wert trotzdem anpassen (er erscheint z.B. im Emulator oder bei Server-seitigem Geocoding):
headers: { "User-Agent": "DEIN-PROJEKT-NAME/1.0" },Diese Dateien enthalten malziME-spezifische Inhalte (Domain, Firma, Kontakt) die du durch deine eigenen ersetzen musst:
| Datei | Was aendern |
|---|---|
public/index.html |
<title>, <meta> (description, author, canonical, OG-Tags, Twitter Cards), Structured Data (JSON-LD), Footer, Buy-Me-a-Coffee-Link |
public/impressum.html |
Kompletter Inhalt — dein eigenes Impressum |
public/datenschutz.html |
Kompletter Inhalt — deine eigene Datenschutzerklaerung |
public/og-image.png |
Eigenes Social-Media-Vorschaubild (1200x630px empfohlen) |
public/site.webmanifest |
App-Name und -Beschreibung |
Rechtlich wichtig: Impressum und Datenschutzerklaerung muessen auf dein Unternehmen/deine Person zugeschnitten sein. Kopiere nicht einfach die malziland-Texte.
Datei: .github/workflows/ci.yml
Der CI-Workflow laeuft automatisch bei Push und Pull Request. Er fuehrt Tests, Lint und Secret-Scan aus.
Deploy ist manuell per firebase deploy — es gibt keinen automatischen Deploy-Workflow.
Die UI-Texte, Gemini-Prompts und Tier-Profile liegen in Locale-Dateien:
| Dateien | Inhalt |
|---|---|
public/locales/de.json |
Alle Frontend-UI-Strings |
functions/src/locales/de/prompts.js |
Gemini-Prompts (System-Prompts, Labels, jsonSchemaNormal + jsonSchemaBoost) |
functions/src/locales/de/animals.js |
Tier-Easter-Egg-Profile |
Wenn du die Texte anpassen oder eine neue Sprache hinzufuegen willst:
- Frontend: Kopiere
de.jsonnachXX.json, uebersetze die Werte, trage den Code inmanifest.jsonein - Backend: Erstelle
functions/src/locales/XX/prompts.js+XX/animals.js, trage den Code inmanifest.jsonein - Testen mit
?lang=XXin der URL
Die Cloud Functions benoetigen Firebase Secrets fuer Admin-Endpunkte und optionale Push-Benachrichtigungen:
# Pflicht: Admin-Token fuer Boost/Reset-Endpunkte
firebase functions:secrets:set ADMIN_SECRET
# Optional: ntfy Push-Benachrichtigungen bei Limit-Erreichung
firebase functions:secrets:set NTFY_URL # z.B. https://ntfy.example.com
firebase functions:secrets:set NTFY_TOPIC # z.B. malzime-alertsWenn du keine ntfy-Benachrichtigungen willst, setze die Secrets auf einen Platzhalter-Wert (z.B. none). Der Code erkennt ungueltige URLs und sendet dann keine Benachrichtigungen.
Das Standard-Stundenlimit liegt bei 500 Analysen/Stunde. Du kannst es in functions/src/config.js aendern:
HOURLY_LIMIT: 500, // Maximale Analysen pro StundeDatei: .github/FUNDING.yml
Ersetze malzime mit deinem eigenen Buy-Me-a-Coffee-Username, oder entferne die Datei.
Fuer lokale Entwicklung muessen die Google Cloud APIs authentifiziert sein:
gcloud auth application-default loginDann den Emulator starten:
firebase emulators:start --only functions,hostingOeffne http://localhost:5000 — die App sollte funktionieren.
Tipp: Im Emulator brauchen die Vision und Vertex AI APIs trotzdem Internet-Zugang — sie laufen nicht lokal.
# Alles deployen
firebase deploy --only functions,hostingDeine Instanz ist jetzt unter https://DEIN-PROJEKT.web.app erreichbar.
- Firebase Console > Hosting > Benutzerdefinierte Domain hinzufuegen
- DNS-Eintraege bei deinem Domain-Anbieter setzen
- CORS-Liste in
functions/src/domains.jsum deine Domain erweitern - Neu deployen:
firebase deploy --only functions
Bevor du live gehst:
-
functions/src/domains.jsenthaelt deine Domains - Impressum und Datenschutzerklaerung sind auf dich zugeschnitten
- Meta-Tags (OG, Twitter, canonical) zeigen auf deine Domain
- User-Agent in geocoding.js enthaelt deinen Projektnamen
- Eigenes OG-Image erstellt
- Locale-Dateien angepasst (falls gewuenscht)
- Firebase Secrets gesetzt: ADMIN_SECRET (+ optional NTFY_URL, NTFY_TOPIC)
- Firestore Security Rules deployed:
firebase deploy --only firestore - Tests laufen:
cd functions && npm testundnpm run test:frontend - Lokal getestet: Bild hochladen funktioniert
| API | Aufrufe | Was |
|---|---|---|
| Vision API | 1 Call, 2 Features | TEXT_DETECTION + LABEL_DETECTION |
| Gemini 2.5 Flash | 3 Calls | 1x Bildbeschreibung (multimodal) + 2x Profil (normal + boost, parallel) |
| Cloud Functions | 1 Invocation | ~5–15 Sekunden, 512 MiB RAM |
| Posten | Preis | Kostenlos/Monat |
|---|---|---|
| Vision API (pro Feature) | $1.50 / 1.000 Bilder | Erste 1.000 Bilder pro Feature |
| Gemini 2.5 Flash Input | $0.30 / 1 Mio. Tokens | — |
| Gemini 2.5 Flash Output | $2.50 / 1 Mio. Tokens | — |
| Firebase Hosting | $0.15 / GB Transfer | 10 GB/Monat |
| Cloud Functions | nutzungsbasiert | 2 Mio. Aufrufe/Monat |
| Posten | Rechnung | Kosten |
|---|---|---|
| Vision API | 60 Units (innerhalb Frei-Kontingent) | $0.00 |
| Gemini Input | ~150.000 Tokens | $0.05 |
| Gemini Output | ~150.000 Tokens | $0.38 |
| Cloud Functions + Hosting | minimal | $0.00 |
| Gesamt | ~$0.43 |
Bei kleinen Workshops (unter 1.000 Bilder/Monat) ist die Vision API kostenlos. Hauptkostentreiber ist Gemini Output (~90% der Kosten).
Neue Google Cloud Konten erhalten $300 Startguthaben. Die vollstaendige Kostenaufstellung mit Preistabellen findest du in docs/SETUP.md.
Oeffne ein Issue auf GitHub — wir helfen gerne.