Biz Next.js Chatbot OpenRouter — AI-Chatbot-Floating-Widget in 1 Schritt auf der Website installieren
Dieser Skill fügt einen AI-Chatbot als Floating-Widget in ein bestehendes Next.js-Projekt ein. Das Widget befindet sich in der unteren rechten Ecke, ist voll responsive auf allen 3 Bildschirmgrößen, ruft LLM über OpenRouter auf, nutzt eine Wissensdatenbank aus FAQ + Kurs-/Produktdokumenten, rendert Markdown in Assistenten-Bläschen (fett für Zahlen/Preise, Aufzählungslisten, klickbare Links, Inline-Code) mittels react-markdown + remark-gfm, und extrahiert und speichert automatisch Leads (Name + Telefon + E-Mail) in KV (Upstash Redis / Vercel KV), sobald der Nutzer die vollständigen Informationen im Chat bereitstellt — der Admin kann diese über das /admin-Dashboard einsehen. Ziel: Solopreneure / Kursersteller mit automatischem 24/7-Support-Bot + passiver Lead-Erfassung direkt auf der Landingpage, keine verpassten Chat-Anfragen.
Grundsatz: Erkenne alles automatisch, was möglich ist (Next.js-Version, App/Pages Router, TS/JS, Tailwind/CSS), frage den Benutzer nur nach den 4 wirklich notwendigen Dingen: (1) welches Projekt bei mehreren, (2) FAQ, (3) Produktdokumente, (4) Ton/Brand-Name. Der Rest ist Code → live in wenigen Minuten.
Wann verwenden
Der Benutzer möchte:
- Einen AI-Chatbot zur Kundenunterstützung auf die Landingpage (Kurs-/Dienstleistungsverkauf) setzen
- Die Beantwortung wiederholter Fragen (Preis, Ablauf, Rückerstattung, Zielgruppe...) reduzieren
- Ein kompaktes Chat-Widget in der unteren rechten Ecke, das den Inhalt nicht verdeckt
- Einen Chatbot, der die Kurs-/Produktinhalte genau versteht (FAQ-gesteuert)
- Ein bestehendes Next.js-Projekt (gerade
/biz-sales-page-layoutausgeführt, oder ein älteres Projekt)
Wann NICHT verwenden
- Das Projekt ist kein Next.js (reines React/Vite, Vue, Svelte, einfaches HTML) → dieser Skill ist auf Next.js spezialisiert. Eine Anpassung ist möglich, aber nicht optimal.
- Es wird ein RAG-Chatbot (Retrieval-Augmented) mit einer Wissensdatenbank von tausenden Seiten benötigt → eine Vektor-DB (Pinecone/Supabase pgvector) ist erforderlich; dieser Skill verwendet einen einfachen System-Prompt, geeignet für ≤ 20K Token Wissen.
- Es wird ein Sprach-Chatbot / multimodaler Chatbot (Bildversand) benötigt → dieser Skill ist text-only.
- Es wird eine Speicherung des Chatverlaufs pro Benutzer in einer DB benötigt → dieser Skill ist zustandslos, mit flüchtigen Sitzungen; kann später erweitert werden.
- Das Backend ist nicht Vercel-freundlich (erfordert Long Polling, persistentes WebSocket) → OpenRouter-Streaming funktioniert gut auf Vercel Edge, aber für separates WS sind andere Lösungen nötig.
Ausgabe für den Benutzer
Nach Ausführung des Skills:
-
Neue Dateien im Next.js-Projekt des Benutzers:
components/Chatbot.tsx(oder.jsx) — Widget-UI (rendert Markdown viareact-markdown+remark-gfm)app/api/chat/route.ts(App Router) ODERpages/api/chat.ts(Pages Router) — API-Proxy zum Aufruf von OpenRouter + automatische Lead-Extraktion nach dem Streamlib/chatbot-knowledge.ts(oder.js) — Wissensdatenbank + System-Prompt (enthält Block ANTWORTFORMATIERUNG + Block AKTIVE LEAD-ERFASSUNG)lib/chat-lead.ts— NUR wenn das Projekt KV/Upstash hat — Extraktor + Speicherer, Deduplizierung nach Telefonnummer, TTL 90 Tage, Namespacechat-lead:{phone}- Markdown-Stile
.chatbot-mdanapp/globals.cssangehängt (austemplates/chatbot-markdown-styles.css) .env.localwird erstellt/ergänzt mitOPENROUTER_API_KEY=(Platzhalter).env.example(falls noch nicht vorhanden) zur Dokumentation der Umgebungsvariablen- Einbindung von
<Chatbot />inapp/layout.tsxoderpages/_app.tsx
-
Zusätzlich installierte Pakete (über den aus der Lockdatei erkannten Paketmanager):
react-markdown— sicheres Rendern von Markdown (keindangerouslySetInnerHTMLnötig)remark-gfm— GitHub Flavored Markdown (Tabellen, Autolink, Durchgestrichen)
-
Klare Anweisungen am Ende der Sitzung:
- 3 Schritte, die der Benutzer selbst ausführen muss: (a) OpenRouter API-Key holen, (b) in
.env.localeinfügen, (c)npm run devzum Testen - Anleitung zum Wechsel des Modells zwischen Gemini und Sonnet
- Anleitung zum späteren Aktualisieren der Wissensdatenbank
- 3 Schritte, die der Benutzer selbst ausführen muss: (a) OpenRouter API-Key holen, (b) in
Arbeitsablauf
Schritt 1 — Next.js-Projekt erkennen
Suche nach Next.js-Projektkandidaten. Ausführen:
# Suche nach package.json mit "next" in den Abhängigkeiten, maximale Tiefe 4
find /Users/tonyhoang/Documents/GitHub -maxdepth 4 -name "package.json" -not -path "*/node_modules/*" 2>/dev/null | xargs grep -l '"next"' 2>/dev/null | head -20
(Falls sich der Benutzer in einem bestimmten Arbeitsverzeichnis befindet, priorisiere die Suche ab cwd abwärts, fallback auf ~/Documents/GitHub, falls nichts gefunden.)
Verzweigung:
- 0 Projekte: Benutzer informieren und abbrechen. Vorschlag: "Haben Sie ein Next.js-Projekt? Falls nicht, möchte ich mit
/biz-sales-page-layoutein neues erstellen und dann zurückkommen?" - 1 Projekt: Pfad vor dem Fortfahren mit dem Benutzer bestätigen: "Ich werde den Chatbot in [Pfad] installieren. Sind Sie einverstanden?"
- ≥ 2 Projekte: Pfade + Namen (
nameaus package.json) in einer nummerierten Liste auflisten, Benutzer zur Auswahl auffordern: "Ich habe N Next.js-Projekte gefunden. In welches möchten Sie den Chatbot installieren?"
Schritt 2 — Projektkontext ermitteln
Nach Bestätigung des Projekts durch den Benutzer, lesen:
-
package.json→ prüfen:- TypeScript (ist
typescriptin den Abhängigkeiten?) - Tailwind (ist
tailwindcssin den devDependencies?) - Paketmanager (Lockdatei:
pnpm-lock.yaml→ pnpm,yarn.lock→ yarn, Standardnpm) - Next.js-Version
- TypeScript (ist
-
Verzeichnisstruktur → prüfen:
- Existiert
app/-Verzeichnis → App Router - Existiert
pages/-Verzeichnis (und keinapp/) → Pages Router - Beide existieren → Priorisiere App Router für neue Dateien (Next.js migriert zu App Router)
src/-Wrapper → Pfade anpassen (z.B.src/app/,src/components/)
- Existiert
-
tsconfig.json→ Pfad-Alias prüfen (@/*→./src/*oder./*) -
.env.local,.env.example→ prüfen, ob bereits vorhanden -
KV/Upstash-Verfügbarkeit (für automatische Lead-Erfassung):
package.jsonenthält@upstash/redisODER@vercel/kv→ KV vorhanden →chat-lead.tserstellen + in die Route einbinden- Datei
src/lib/kv.ts(oderlib/kv.ts) mit Exportkvvorhanden → vorhandenen Helfer nutzen (Camp-Muster) - Kein KV → Erstellung von
chat-lead.tsüberspringen, Benutzer informieren: "Projekt hat kein KV — automatische Lead-Erfassung ist deaktiviert. Ich kann mit/biz-setup-sepay-paymentzuerst KV installieren und dann zurückkommen, um die Lead-Erfassung zu aktivieren, oder Sie überspringen diesen Schritt."
Diese Beobachtungen in einer kleinen Tabelle für die späteren Schritte speichern.
Schritt 3 — Wissensdatenbank vom Benutzer sammeln
Dem Benutzer 4 Fragen stellen (in einer Nachricht zusammenfassen, damit der Benutzer alles auf einmal beantworten kann):
Für eine präzise Antwort des Chatbots benötige ich 4 Dinge:
1. **FAQ** — Liste häufig gestellter Fragen + Antworten (Preis, Ablauf, Rückerstattung, Zielgruppe, Lernzeit, Unterstützung nach dem Kurs...).
Bitte direkt hier einfügen ODER den Dateipfad angeben (.md / .txt / .docx).
2. **Produkt-/Kursdokumentation** — Detaillierte Kursbeschreibung: Name, Inhalt jedes Moduls, Lernergebnisse, Dozent, Boni, Preisstufen (falls vorhanden).
Ebenfalls einfügen oder Dateipfad angeben.
3. **Brand-Name + Ton** — Name der Marke/des Kurses, damit der Chatbot sich vorstellen kann (z.B. "Assistent von AI Mastery"). Ton des Bots: freundlich (Standard) / formell / locker.
4. **Modell** — Standardmäßig `google/gemini-3-flash-preview` (schnell, günstig, gut für Support geeignet). Möchten Sie `anthropic/claude-sonnet-4.6` (höhere Qualität, ~10x teurer) für die frühe Phase? Dann sagen Sie Bescheid.
Können Sie alles auf einmal beantworten?
Wenn der Benutzer antwortet:
- Wird nur ein Dateipfad angegeben → Datei mit dem Read-Tool lesen.
- Wird der Inhalt direkt eingefügt → den eingefügten Inhalt verwenden.
- Sagt der Benutzer "Generiere bitte Platzhalter für mich" → generische FAQ-Platzhalter erstellen und mit
// TODO: user fill inmarkieren, damit der Benutzer weiß, dass er sie aktualisieren muss. - Kein Brand-Name → Standard "AI-Assistent" und Anrede "Sie".
Schritt 4 — Dateien im Projekt generieren
Die Vorlagen im templates/-Verzeichnis dieses Skills lesen und an das Projekt anpassen. Die Vorlagen:
templates/chatbot-knowledge.ts— Modul, das Wissensdatenbank und systemPrompt exportiert. FAQ, Produktinfo, Brand-Name und Ton hier einfügen. Enthält bereits Block ANTWORTFORMATIERUNG (Markdown-Regeln) + Block AKTIVE LEAD-ERFASSUNG (bringt dem LLM bei, nach Name/Telefon/E-Mail zu fragen, wenn Kaufsignale erkannt werden, zu danken und zu bestätigen, wenn der Benutzer die Daten angibt, NICHT "in der Datenbank gespeichert" sagen).templates/Chatbot.tsx— Widget-Komponente, Tailwind-first. Importiertreact-markdown+remark-gfm, rendert Assistenten-Nachrichten mit<ReactMarkdown remarkPlugins={[remarkGfm]}>(nur Assistent — Benutzernachrichten bleiben einfacheswhitespace-pre-wrap). Wenn das Projekt KEIN Tailwind hat → Fallbacktemplates/Chatbot-noTailwind.tsx+templates/chatbot.module.css.templates/chat-route-app.ts— API-Route für App Router (app/api/chat/route.ts). Enthält bereits den HookpersistLeadIfReady, der nach Stream-Ende im Hintergrund ausgeführt wird — blockiert nicht die Antwort.templates/chat-route-pages.ts— API-Route für Pages Router (pages/api/chat.ts).templates/chat-lead.ts— NUR erstellen, wenn das Projekt KV/Upstash hat — Regex-Extraktion für vietnamesische Telefonnummern + E-Mail + Namensheuristik (Intro-Muster "Name X" / "ich bin X" / "Name: X"),saveChatLeaddedupliziert nach Telefonnummer, TTL 90 Tage, Key-Namespacechat-lead:{phone}.templates/chatbot-markdown-styles.css— CSS-Snippet für die Klasse.chatbot-md. MUSS an das Ende vonapp/globals.cssangehängt werden (odersrc/app/globals.css/styles/globals.css). Akzentfarbe (#fde68a/#f59e0b) vor dem Anhängen an die Markenfarbpalette des Projekts anpassen.templates/env-instructions.md— Snippet mit Anleitung zum Abrufen des OpenRouter-Keys, Verwendung im letzten Schritt.
Regeln für die Anpassung von Vorlagen:
-
TS vs JS: Wenn das Projekt nur JS hat, die Erweiterung
.ts/.tsxin.js/.jsxändern und Type-Annotationen entfernen (nicht nur die Dateinamen ändern). Die Beispieldatei lesen, parsen, Typen entfernen, die Datei schreiben. -
Pfad-Alias: Wenn
tsconfig@/*auf./src/*abbildet, müssen die Importe in der Vorlage@/lib/chatbot-knowledgeverwenden und die Datei insrc/lib/abgelegt werden. Ohne Alias relative Pfade verwenden. -
Modell: Platzhalter
__MODEL_ID__durch das vom Benutzer gewählte Modell ersetzen (google/gemini-3-flash-previewoderanthropic/claude-sonnet-4.6). -
Brand:
__BRAND_NAME__und__BRAND_TONE__ersetzen. -
Wissen:
systemPromptaus FAQ + Produktinfo in einer klaren, strukturierten Form aufbauen (siehe Vorlage). Den Block ANTWORTFORMATIERUNG im systemPrompt beibehalten — das lehrt das LLM, Markdown auszugeben, das für kleine Chat-Bläschen geeignet ist (fett statt Überschriften, kurze einzeilige Aufzählungspunkte). -
Markdown-Rendering-Pakete installieren (ERFORDERLICH — sonst zeigt der Chatbot rohes
**bold**anstatt fett gedruckten Text im Bläschen):# Lockdatei erkennen → richtigen Paketmanager wählen npm install react-markdown remark-gfm # oder: pnpm add react-markdown remark-gfm # oder: yarn add react-markdown remark-gfm -
Markdown-Stile anhängen:
templates/chatbot-markdown-styles.csslesen, Akzentfarbe an die Markenfarbpalette des Projekts anpassen (inglobals.cssnach--color-primaryoder ähnlich suchen), dann an das Ende vonapp/globals.cssanhängen (odersrc/app/globals.css/styles/globals.css). -
Widget einbinden:
- App Router:
app/layout.tsx(odersrc/app/layout.tsx) bearbeiten,import Chatbot from '@/components/Chatbot'und<Chatbot />direkt vor</body>einfügen. Vor der Bearbeitung die aktuellelayout.tsxlesen, um Metadaten, Schriftarten und Provider zu erhalten. - Pages Router:
pages/_app.tsxbearbeiten, Return-Wert umschließen:<><Component {...pageProps} /><Chatbot /></>. Vorhandene_applesen, bestehende Provider beibehalten.
- App Router:
-
Automatische Lead-Erfassung einbinden (nur durchführen, wenn KV in Schritt 2 erkannt wurde):
templates/chat-lead.tsinlib/chat-lead.ts(odersrc/lib/chat-lead.ts) kopieren.- Wenn das Projekt NOCH KEINE
lib/kv.tshat → erstellen:import { Redis } from "@upstash/redis"; export const kv = Redis.fromEnv(); - Route-Handler importieren:
import { extractLeadFromMessages, saveChatLead } from "@/lib/chat-lead" - In der Stream-Schleife:
assistantTextverfolgen (Delta akkumulieren), wenn Stream geschlossen →persistLeadIfReady(history, assistantText)aufrufen (fire-and-forget, NICHT await im Response-Pfad). - System-Prompt: Sicherstellen, dass der Block AKTIVE LEAD-ERFASSUNG bereits in
chatbot-knowledge.tsvorhanden ist (die Vorlage enthält ihn bereits). - Dem Benutzer bestätigen: "Ich habe die automatische Lead-Erfassung aktiviert — wenn ein Kunde Name/Telefon/E-Mail im Chat eingibt, speichert das System automatisch im KV-Namespace
chat-lead:{TELEFONNUMMER}. Sie können die Leads unter/admineinsehen (falls/biz-admin-leads-dashboardinstalliert ist)."
Schritt 5 — .env.local + .gitignore einrichten
-
Prüfen, ob
.env.localbereits existiert?- Nein: Neu erstellen mit:
# OpenRouter API-Key — Holen unter https://openrouter.ai/keys OPENROUTER_API_KEY= # Optional: Site-URL für OpenRouter-Referrer-Tracking (hilft bei Rate-Limiting) NEXT_PUBLIC_SITE_URL=http://localhost:3000 - Ja: Die beiden Variablen anhängen, falls sie noch nicht vorhanden sind, vorhandene Variablen nicht überschreiben.
- Nein: Neu erstellen mit:
-
.env.exampleaktualisieren (neu erstellen, falls nicht vorhanden):OPENROUTER_API_KEY=sk-or-v1-xxxxx NEXT_PUBLIC_SITE_URL=https://your-domain.com -
Prüfen, ob
.gitignorebereits.env.localenthält? Falls nicht →.env.localund.env*.localanhängen.
Schritt 6 — Bericht an den Benutzer
Eine klare Zusammenfassung mit 4 Teilen ausgeben:
✅ Chatbot wurde erfolgreich in [Projektname] installiert
📁 Erstellte Dateien:
- components/Chatbot.tsx (rendert Markdown via react-markdown + remark-gfm)
- app/api/chat/route.ts
- lib/chatbot-knowledge.ts
- app/globals.css (Markdown-Stile .chatbot-md angehängt)
- .env.local (Platzhalter)
📦 Installierte Pakete: react-markdown, remark-gfm
🔑 3 Schritte, die Sie selbst ausführen müssen, damit der Chatbot funktioniert:
1. OpenRouter API-Key holen:
- Gehen Sie zu https://openrouter.ai → Registrieren (Sie können sich auch mit Google anmelden)
- Gehen Sie zu https://openrouter.ai/keys → Create Key
- Laden Sie Guthaben auf (https://openrouter.ai/credits) — Gemini 3 Flash ist günstig, $5 reichen für tausende Chat-Anfragen
- Kopieren Sie den Key im Format `sk-or-v1-xxxxx`
2. Fügen Sie ihn in die Datei `.env.local` ein:
OPENROUTER_API_KEY=sk-or-v1-xxxxx-hier-einfügen
3. Testen:
[npm/pnpm/yarn] run dev
Öffnen Sie http://localhost:3000 → klicken Sie auf die Sprechblase unten rechts
🔄 Modell zwischen Gemini ↔ Sonnet wechseln:
Öffnen Sie `app/api/chat/route.ts`, ändern Sie die Variable `model:` am Anfang der Datei.
- `google/gemini-3-flash-preview` (Standard, $0.075/1M Input, schnell)
- `anthropic/claude-sonnet-4.6` (Premium, ~$3/1M Input, bessere Qualität)
📚 Wissensdatenbank später aktualisieren:
Bearbeiten Sie `lib/chatbot-knowledge.ts` — fügen Sie FAQ und productInfo hinzu/ändern Sie sie, speichern Sie, Hot Reload.
Mobile-first responsives Design
Das Widget muss 3 Breakpoints erreichen:
| Breakpoint | Verhalten |
|---|---|
| ≤ 640px (mobil) | Klick auf Sprechblase → Vollbild-Overlay (z-index 9999), Header mit X-Schaltfläche zum Schließen. Input am unteren Bildschirmrand verankert mit safe-area-inset, um nicht von der Tastatur verdeckt zu werden. |
| 641–1023px (Tablet) | Panel 380px × 70vh, unten rechts verankert mit 16px Abstand. |
| ≥ 1024px (Desktop) | Panel 400px × 600px, unten rechts verankert mit 24px Abstand. Sprechblase 60px rund. |