Compare commits

..

9 Commits

Author SHA1 Message Date
b27c69c4bd Web-Demo Fix: geteilte Anschluesse blockierten den ersten Versuch
Fehler: Der anonyme Erst-Versuch war auf 1 pro IP (30 Tage) begrenzt.
Teilen sich mehrere Menschen eine Leitung (Familie, WLAN, Mobilfunk/CGNAT),
bekam der Zweite sofort 'E-Mail noetig' statt einer Analyse. Trat auch
beim Testen ueber denselben Anschluss auf.

- IP- und Anon-Zaehler jetzt TAEGLICH (Datum im Schluessel), 48h TTL
- Anonyme Erst-Analysen pro Anschluss/Tag: 3 (statt 1/30 Tage)
- IP-Gesamtlimit pro Tag: 8 (statt 3/30 Tage)
- 'Wallet'-Schutz unveraendert: globales Tagesbudget 100 + Turnstile +
  E-Mail-Hash (dauerhaft 1x/Adresse)
- Client: email_noetig markiert den Browser NICHT mehr als verbraucht
  (sonst dauerhafte Blockade ohne gelungene Analyse); localStorage-Key
  auf 'bk_demo_v2' umbenannt -> setzt falsche Testphasen-Staende zurueck

Ende-zu-Ende verifiziert: frischer Erst-Upload liefert wieder das Ergebnis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:51:37 +02:00
2f770ebfad Startseite: Demo und Warteliste als gleichwertige Knoepfe (Mischung)
- Warteliste nicht mehr nur Textlink, sondern zweiter Knopf (heller,
  umrandeter Sekundaer-Stil .cta-sek) neben dem Demo-Knopf
- Beide Wege mit eigenem Nutzen benannt: Testen (eigener Brief, kein Konto)
  / Warteliste (5 Gratis-Analysen zum Start)
- Bald-im-App-Store-Stempel auf eigene Zeile

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 13:17:56 +02:00
5557b26364 Startseite: Web-Demo zur Haupt-Handlung machen
- Hero-Knopf ist jetzt die Demo ('Brief testen — 2x gratis', groesser),
  Warteliste rueckt zum sekundaeren Textlink
- Subline: 'Mit Ihrem eigenen Brief, kein Konto, sofort im Browser'
- Zusaetzliche Probier-Box direkt nach dem Vorher/Nachher-Beispiel
  ('Genau das — mit Ihrem Brief') fuer den zweiten Impuls

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 13:12:55 +02:00
ec6ec22421 Web-Demo: 2 Gratis-Analysen direkt auf der Webseite
Worker (/demo auf behoerdenklar-proxy):
- Turnstile-Verifikation serverseitig (Bot-Mauer)
- Analyse 1 anonym (1x pro IP/30 Tage), Analyse 2 nur mit E-Mail
  (SHA-256-Hash mit Pepper, dauerhaft — nie Klartext gespeichert)
- IP-Gesamtlimit 3/30 Tage, globales Tagesbudget 100 (~2,50 EUR Deckel)
- Wegwerf-Mail-Blockliste, 5-MB-Limit, CORS nur eigene Domain
- Prompt/Schema identisch zur App (ohne Antwort-Generator)

Webseite:
- demo.html im Papier-Design: Einwilligung, Upload mit Client-Downscaling
  (2000px/JPEG wie App), Ampel-Logik, Ergebnis-Karten, Warteliste-CTA
  mit vorbelegter E-Mail, gestaffelter Ablauf 1. anonym / 2. mit E-Mail
- Startseite verlinkt Demo im Hero
- Datenschutz: neuer Abschnitt 8 Gratis-Demo (Einwilligung, Turnstile,
  E-Mail-Hash), Folgeabschnitte neu nummeriert; Sitemap + /demo

Ende-zu-Ende getestet: echte Analyse (Jobcenter-Testbrief korrekt erklärt,
Ampel erkennt fruehere Absagefrist), Schummler-Szenarien (Browser-Loeschen,
doppelte E-Mail) serverseitig abgefangen. Dabei entdeckt: Anthropic-Key
war ungueltig -> erneuert (App-Analyse funktionierte wieder).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:06:03 +02:00
02523b0467 SEO Quick Wins 1-5: Social-Vorschau, Title, FAQ-Schema, Sitemap
- Open-Graph-Tags + Vorschaubild (1200x630, Papier-Design) auf allen
  7 Sprachseiten, lokalisierte og:title/description je Sprache
- Title-Tag mit Suchwort vorn: 'Behördenbriefe einfach erklärt – per Foto'
- Meta-Description gestrafft (146 Zeichen, mit Handlungsaufruf)
- FAQPage-Schema (JSON-LD) mit 6 Fragen
- 2 neue FAQ-Einträge (Long-Tail: Jobcenter, Ausländerbehörde, Sprachen)
- canonical + hreflang x-default auf allen Seiten
- robots.txt, sitemap.xml, favicon.svg

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 22:24:37 +02:00
78d8c6246a Marketing: Prompts + Anleitung für KI-Werbevideo
- App-Beschreibung als wiederverwendbarer Prompt-Block (EN/DE)
- 3 Szenen-Prompts (Problem/Lösung/Erleichterung) + Zielgruppen-Varianten
- App-Szene bewusst als echte Bildschirmaufnahme, nicht KI-generiert
- Texteinblendungen, Formate, Tool-Übersicht

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 09:27:00 +02:00
30702677b6 Marketing: fertige E-Mails für Diakonie Donnersbergkreis + Caritas KL
- Diakonie-Version: Zielgruppe breiter (nicht nur Migration)
- Caritas-Version: Migrationsfokus, Adresse Engelsgasse recherchiert
- Status-Tabelle zum Nachfassen ergänzt

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:41:07 +02:00
24d44f3d69 Warteliste: echtes Brevo-Anmeldeformular statt Mailto-Button
- E-Mail-Feld + Knopf im Papier-Design auf allen 7 Landingpages
  (DE/EN/TR/AR/UK/RU/PL), lokalisierte Platzhalter/Button-Texte
- POST an Brevo (Double-Opt-in aktiv), Honeypot gegen Spam
- Besucher können sich jetzt mit 2 Klicks eintragen statt eine Mail
  abzuschicken — deutlich niedrigere Hürde
- DE-Bonustext präzisiert: Code kommt per Mail, sobald die App fertig ist

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:26:50 +02:00
baf316fd08 Web-Analytics: Token auf neuen, korrekt registrierten Wert umgestellt
Der erste Token (2182...) wurde bei der Einrichtung nie in Cloudflare
gespeichert. Neuer Token (11f0...) ist jetzt richtig registriert und in
der Web-Analytics-Liste sichtbar. Alle 9 Seiten aktualisiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 08:33:35 +02:00
20 changed files with 1478 additions and 39 deletions

View File

@@ -0,0 +1,9 @@
---
name: .claude
description: Describe what this custom agent does and when to use it.
tools: Read, Grep, Glob, Bash # specify the tools this agent can use. If not set, all enabled tools are allowed.
---
<!-- Tip: Use /create-agent in chat to generate content with agent assistance -->
Define what this custom agent does, including its behavior, capabilities, and any specific instructions for its operation.

View File

@@ -0,0 +1,9 @@
---
name: claude
description: Describe what this custom agent does and when to use it.
tools: Read, Grep, Glob, Bash # specify the tools this agent can use. If not set, all enabled tools are allowed.
---
<!-- Tip: Use /create-agent in chat to generate content with agent assistance -->
Define what this custom agent does, including its behavior, capabilities, and any specific instructions for its operation.

View File

@@ -0,0 +1,112 @@
# E-Mails Nr. 2 + 3: Diakonie Donnersbergkreis & Caritas Kaiserslautern
Absender: behoerdenbriefhelfer@gmail.com
Anhänge (wie bei der MBE-Mail): BehoerdenKlar-Datenschutz.pdf + die 2
Screenshots aus marketing/screenshots/
Versandwoche: KW 30 (bis Freitag, 24.07.2026)
---
## E-Mail Nr. 2 — Haus der Diakonie Donnersbergkreis
**An:** slb.kibo@diakonie-pfalz.de
**Betreff:** App aus dem Donnersbergkreis erklärt Behördenbriefe in einfacher Sprache — 10 Minuten Feedback aus Ihrer Praxis?
Sehr geehrtes Team des Hauses der Diakonie,
mein Name ist Justin Klein, ich komme aus Winnweiler und habe eine
iPhone-App entwickelt, die Behördenbriefe verständlich macht:
Brief fotografieren — die App erklärt in einfacher Sprache (A2), was das
Amt will, zeigt Fristen und Termine mit Erinnerung und erstellt auf Wunsch
einen Antwort-Entwurf.
Ich denke dabei nicht nur an Menschen mit anderer Muttersprache (die App
übersetzt in 9 Sprachen, unter anderem Arabisch, Türkisch und Ukrainisch),
sondern an alle, die bei Ihnen Rat suchen: Menschen, denen Amtsdeutsch
Angst macht, die Fristen übersehen oder Briefe erst einmal liegen lassen.
Ich glaube, das könnte die Menschen entlasten, die zu Ihnen kommen — und
vielleicht auch Ihre Beratungszeit: weniger Vorlesen, mehr Lösen.
Bevor die App im App Store erscheint, möchte ich sie Menschen aus der
Praxis zeigen und ehrliches Feedback einholen: Würde das Ihren Klientinnen
und Klienten wirklich helfen? Was fehlt? **Dürfte ich dafür einmal für
1015 Minuten bei Ihnen in Kirchheimbolanden vorbeikommen?** Ich richte
mich ganz nach Ihrer Zeit.
Zum Datenschutz, weil das bei Behördenpost besonders zählt: Alle Briefe
bleiben verschlüsselt auf dem Handy der Nutzer, es gibt kein Konto, kein
Tracking und keine Werbung — eine Übersicht liegt als PDF bei. Die ersten
Analysen sind kostenlos, Vielnutzer zahlen später ein kleines Abo
(2,99 €/Monat).
Webseite (auch auf Arabisch, Türkisch u. a.): https://behoerdenklar.pages.dev
Mit freundlichen Grüßen
Justin Klein
Winnweiler · behoerdenbriefhelfer@gmail.com
---
## E-Mail Nr. 3 — Caritas-Zentrum Kaiserslautern (Migrationsberatung)
**An:** Migration.Kaiserslautern@caritas-speyer.de
**Betreff:** App aus der Region erklärt Behördenbriefe in einfacher Sprache — 10 Minuten Feedback aus Ihrer Beratungspraxis?
Sehr geehrtes Team der Migrationsberatung,
mein Name ist Justin Klein, ich komme aus Winnweiler und habe eine
iPhone-App entwickelt, die Behördenbriefe verständlich macht:
Brief fotografieren — die App erklärt in einfacher Sprache (A2), was das
Amt will, zeigt Fristen und Termine mit Erinnerung und erstellt auf Wunsch
einen Antwort-Entwurf. Die Erklärung lässt sich in 9 Sprachen übersetzen,
unter anderem Arabisch, Türkisch, Ukrainisch und Farsi — die deutschen
Fachbegriffe bleiben dabei sichtbar, damit Ihre Klientinnen und Klienten
sie im Brief wiederfinden.
Ich glaube, das könnte die Menschen entlasten, die zu Ihnen kommen — und
vielleicht auch Ihre Beratungszeit: weniger Vorlesen, mehr Lösen.
Bevor die App im App Store erscheint, möchte ich sie Menschen aus der
Praxis zeigen und ehrliches Feedback einholen: Würde das Ihren Klientinnen
und Klienten wirklich helfen? Was fehlt? **Dürfte ich dafür einmal für
1015 Minuten bei Ihnen in der Engelsgasse vorbeikommen?** Ich richte
mich ganz nach Ihrer Zeit.
Zum Datenschutz, weil das bei Behördenpost besonders zählt: Alle Briefe
bleiben verschlüsselt auf dem Handy der Nutzer, es gibt kein Konto, kein
Tracking und keine Werbung — eine Übersicht liegt als PDF bei. Die ersten
Analysen sind kostenlos, Vielnutzer zahlen später ein kleines Abo
(2,99 €/Monat).
Webseite (auch auf Arabisch, Türkisch u. a.): https://behoerdenklar.pages.dev
Mit freundlichen Grüßen
Justin Klein
Winnweiler · behoerdenbriefhelfer@gmail.com
---
## Kontaktdaten (recherchiert 22.07.2026)
- **Caritas-Zentrum Kaiserslautern:** Engelsgasse 1, 67657 Kaiserslautern,
Tel. 0631 36120-222, Migration.Kaiserslautern@caritas-speyer.de
(Quelle: caritas.de-Adressverzeichnis)
- **Haus der Diakonie Donnersbergkreis:** Kirchheimbolanden,
slb.kibo@diakonie-pfalz.de (SLB = Soziale Lebensberatung)
## Nachfassen
- Ohne Antwort nach 57 Tagen: freundlich anrufen und auf die Mail
verweisen (Caritas: 0631 36120-222).
- Status-Übersicht:
| Stelle | Mail raus | Nachgefasst | Antwort |
|---|---|---|---|
| MBE Donnersberg (Kibo) | 17.07.2026 | geplant 23./24.07. | — |
| Diakonie Donnersbergkreis | — | — | — |
| Caritas Kaiserslautern | — | — | — |

View File

@@ -0,0 +1,147 @@
# KI-Video für Werbung — Prompts & Anleitung
## Wichtig vorweg: Wie KI-Video wirklich funktioniert
1. **Ein Prompt = ein kurzer Clip** (meist 510 Sekunden). Ein fertiger
Werbespot besteht aus 34 Clips, die du hinterher aneinanderhängst.
2. **KI kann keinen lesbaren Text.** Buchstaben werden zu Kauderwelsch.
Deshalb steht in allen Prompts unten: Text unscharf / nicht lesbar.
3. **Die App selbst NICHT von der KI zeichnen lassen.** Das sieht falsch aus
und wäre auch unehrlich. Für die App-Szene nimmst du eine **echte
Bildschirmaufnahme** (iPhone: Bildschirmaufnahme in den Einstellungen
aktivieren, oder im Simulator aufnehmen).
**Faustregel:** KI macht die *Gefühle* (Sorge → Erleichterung),
Bildschirmaufnahme macht die *Fakten* (was die App kann).
---
## Teil 1: Die App-Beschreibung
Diesen Block kannst du in jedes KI-Tool kopieren, wenn es Kontext braucht:
> BehördenKlar is a German mobile app that helps people understand official
> letters from government authorities. The user photographs a letter with
> their phone; an AI explains what the letter means in simple, plain German
> (A2 level), highlights deadlines with a traffic-light system, and can
> translate the explanation into 9 languages including Arabic, Turkish,
> Ukrainian and Farsi. It also drafts a reply and sets a reminder.
> Target audience: migrants, elderly people, and anyone who feels anxious
> when a letter from a German authority arrives.
> Tone: calm, respectful, warm, trustworthy — never mocking the user,
> never making bureaucracy look funny. The feeling we sell is RELIEF.
**Deutsch (falls das Tool Deutsch kann):**
> BehördenKlar ist eine App, die Behördenbriefe verständlich macht. Man
> fotografiert den Brief, die App erklärt ihn in einfacher Sprache, zeigt
> Fristen und übersetzt in 9 Sprachen. Zielgruppe: Menschen, die bei Post
> vom Amt unsicher sind. Stimmung: ruhig, respektvoll, warm. Das Gefühl,
> das wir verkaufen, ist Erleichterung.
---
## Teil 2: Die Video-Prompts (3 Szenen)
Prompts sind auf **Englisch** — damit liefern fast alle Tools bessere
Ergebnisse. Einfach kopieren und einzeln generieren lassen.
### Szene 1 — Das Problem (ca. 5 Sek.)
```
Close-up of a worried woman in her thirties sitting at a small kitchen
table in a modest apartment, holding an official government letter with
dense printed text. Soft morning light from a window. She frowns slightly
and rubs her forehead. Shallow depth of field, the text on the paper is
blurred and unreadable. Documentary style, natural colors, 35mm film look,
subtle handheld camera movement.
```
### Szene 2 — Die Lösung (ca. 5 Sek.)
```
Overhead shot of hands holding a smartphone above an official letter lying
on a wooden table. The phone is framing the document to take a photo. Soft
natural daylight, clean minimal composition. The phone screen is not
visible to the camera. Documentary style, warm tones, shallow depth of
field, slow gentle camera movement.
```
### Szene 3 — Die Erleichterung (ca. 5 Sek.)
```
Medium close-up of the same woman looking down at her smartphone. Her
tense expression slowly softens into relief and a small calm smile. She
nods gently, her shoulders relax. Warm morning light from a window behind
her, blurred cozy kitchen background. Documentary style, natural skin
tones, 35mm film look, very subtle camera push-in.
```
### Szene 4 — Die App (KEINE KI!)
Echte Bildschirmaufnahme: Startbildschirm → „Brief scannen" → Ergebnis
mit Ampel. 45 Sekunden reichen.
---
## Varianten (je nach Zielgruppe)
Ersetze in Szene 1 und 3 die Person:
- **Älterer Mann:** `a worried man in his seventies with grey hair`
- **Junger Vater:** `a worried man in his thirties, a child's drawing on
the fridge behind him`
- **Arabischsprachige Zielgruppe:** `a woman in her thirties wearing a
headscarf` — passend für Papas Gruppen
Tipp: Mach zwei Versionen mit verschiedenen Personen. Menschen reagieren
stärker, wenn sie sich selbst wiedererkennen.
---
## Teil 3: Zusammensetzen
**Reihenfolge:** Szene 1 → 2 → 3 → 4 (App) → Schlussbild
**Text-Einblendungen** (der Zuschauer hat oft den Ton aus!):
| Zeit | Text |
|------|------|
| Szene 1 | „Post vom Amt. Und jetzt?" |
| Szene 2 | „Einfach fotografieren." |
| Szene 3 | „In einfachen Worten erklärt." |
| Szene 4 | „Fristen im Blick. 9 Sprachen." |
| Schluss | „BehördenKlar — Brief rein. Klartext raus." + Webseite |
**Musik:** ruhig, warm, kein Techno. Bei Pixabay/YouTube Audio Library
kostenlos: Suche nach „calm hopeful piano".
**Schneiden (kostenlos):** CapCut (Handy + Mac), iMovie oder Canva.
**Formate:** 9:16 (Hochkant) für Instagram/TikTok/WhatsApp-Status,
1:1 für Facebook. Hochkant ist am wichtigsten.
---
## Teil 4: Womit generieren?
Gängige Tools mit Gratis-Kontingent (Stand kann sich ändern — vorher die
aktuellen Konditionen prüfen):
- **Kling AI** — täglich Gratis-Credits, gute Menschen-Darstellung
- **Hailuo / MiniMax** — ebenfalls Gratis-Credits
- **Runway, Pika** — begrenzte Gratis-Versionen
- **Sora / Veo** — nur mit kostenpflichtigem Abo
**Realistische Erwartung:** Rechne mit 510 Versuchen pro Szene, bis eine
gut aussieht. Das ist normal, nicht dein Fehler.
---
## Wichtig: Ehrlich bleiben
- Keine erfundenen App-Bildschirme zeigen — nur echte Aufnahmen.
- Keine erfundenen Bewertungen oder Nutzerzahlen einblenden.
- Solange die App nicht im Store ist: **„Bald verfügbar"** einblenden und
auf die Warteliste verlinken. Sonst sind die Leute enttäuscht und
kommen nicht wieder.

View File

@@ -16,12 +16,18 @@
interface Env { interface Env {
/** Geheimnis: `wrangler secret put ANTHROPIC_API_KEY` */ /** Geheimnis: `wrangler secret put ANTHROPIC_API_KEY` */
ANTHROPIC_API_KEY: string; ANTHROPIC_API_KEY: string;
/** Geheimnis: `wrangler secret put TURNSTILE_SECRET_KEY` (Web-Demo) */
TURNSTILE_SECRET_KEY: string;
/** KV-Namespace für das Rate-Limit (Binding in wrangler.toml) */ /** KV-Namespace für das Rate-Limit (Binding in wrangler.toml) */
RATE_LIMIT: KVNamespace; RATE_LIMIT: KVNamespace;
/** Erlaubte Anfragen pro Gerät und Tag (in wrangler.toml unter [vars]) */ /** Erlaubte Anfragen pro Gerät und Tag (in wrangler.toml unter [vars]) */
TAGES_LIMIT: string; TAGES_LIMIT: string;
/** Erlaubte Anfragen pro IP-Adresse und Tag (in wrangler.toml unter [vars]) */ /** Erlaubte Anfragen pro IP-Adresse und Tag (in wrangler.toml unter [vars]) */
TAGES_LIMIT_IP: string; TAGES_LIMIT_IP: string;
/** Web-Demo: hartes Tagesbudget über alle Nutzer (Kosten-Deckel) */
DEMO_TAGES_BUDGET: string;
/** Web-Demo: max. Analysen pro IP innerhalb von 30 Tagen */
DEMO_LIMIT_IP: string;
} }
const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages'; const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
@@ -44,8 +50,300 @@ function fehler(status: number, typ: string, meldung: string): Response {
); );
} }
// ============================================================
// Web-Demo (/demo): 2 Gratis-Analysen direkt auf der Webseite
// ============================================================
//
// Schutzschichten (jede allein wäre umgehbar, zusammen dicht genug):
// 1. Turnstile-Token (Bot-Mauer, wird serverseitig verifiziert)
// 2. Analyse 1 anonym: max. 1 pro IP / 30 Tage
// 3. Analyse 2 nur mit E-Mail: pro E-Mail (Hash) genau 1 — dauerhaft
// 4. IP-Gesamtlimit über 30 Tage (bremst Verlauf-Löscher)
// 5. Globales Tagesbudget (harter Kosten-Deckel für den Betreiber)
/** Nur die eigene Webseite darf den Demo-Endpunkt aufrufen (CORS). */
const DEMO_ORIGIN_MUSTER = /^https:\/\/([a-z0-9-]+\.)?behoerdenklar\.pages\.dev$/;
/** ~5 MB Datei entsprechen ~6,7 Mio. Base64-Zeichen. */
const DEMO_MAX_BASE64 = 7_000_000;
/** Bekannte Wegwerf-E-Mail-Domains (kleine, pragmatische Liste). */
const WEGWERF_DOMAINS = new Set([
'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'temp-mail.org',
'tempmail.com', 'trashmail.com', 'yopmail.com', 'sharklasers.com',
'getnada.com', 'dispostable.com', 'maildrop.cc', 'throwawaymail.com',
]);
/** Identisch zur App (src/services/analyse.ts) — gleiche Qualität in der Demo. */
const DEMO_SYSTEM_PROMPT = `Du bist ein Assistent, der deutschen Behördenbriefe für Privatpersonen verständlich macht. Die Nutzer sind Deutsche, die Amtsdeutsch schwer verstehen, oder Menschen mit Deutsch als Fremdsprache.
Deine Aufgabe:
1. Lies den fotografierten/hochgeladenen Brief vollständig.
2. Erkläre ihn in einfacher Alltagssprache (Sprachniveau A2/B1): kurze Sätze, keine Schachtelsätze, keine unerklärten Fachbegriffe.
3. Extrahiere Fristen und Termine exakt. Datumsangaben immer als ISO-Format (JJJJ-MM-TT). Wenn du ein Datum nicht sicher lesen kannst, lass das Feld null — erfinde niemals Daten.
4. Erstelle eine konkrete Checkliste, was der Nutzer tun muss.
5. Sei sachlich und beruhigend, nicht alarmierend.
Wichtig: Wenn das Bild kein Behördenbrief ist oder unlesbar ist, schreibe das klar in kernaussage und erklaerung_einfach und lasse frist/termin null.`;
/** Schlanke Demo-Variante des Analyse-Schemas (ohne Antwort-Optionen —
* der Antwort-Generator bleibt der App vorbehalten). */
const DEMO_SCHEMA = {
type: 'object',
additionalProperties: false,
required: ['brieftyp', 'absender', 'kernaussage', 'erklaerung_einfach', 'fachbegriffe', 'frist', 'termin', 'checkliste'],
properties: {
brieftyp: { type: 'string', description: 'Kurze Kategorie des Briefs, z. B. "Einladung Jobcenter".' },
absender: { type: 'string', description: 'Die Behörde, die den Brief geschickt hat.' },
kernaussage: { type: 'string', description: 'Antwort auf "Was will das Amt von mir?" in 2-3 kurzen Sätzen, Sprachniveau A2.' },
erklaerung_einfach: { type: 'string', description: 'Erklärung des gesamten Briefs in einfacher Alltagssprache (A2/B1). Kurze Sätze.' },
fachbegriffe: {
type: 'array',
description: 'Fachbegriffe aus dem Brief mit einfacher Erklärung.',
items: {
type: 'object', additionalProperties: false, required: ['begriff', 'erklaerung'],
properties: { begriff: { type: 'string' }, erklaerung: { type: 'string' } },
},
},
frist: {
description: 'Frist, bis wann reagiert werden muss. null wenn keine Frist im Brief steht.',
anyOf: [
{
type: 'object', additionalProperties: false, required: ['datum', 'aktion'],
properties: { datum: { type: 'string', description: 'ISO JJJJ-MM-TT' }, aktion: { type: 'string' } },
},
{ type: 'null' },
],
},
termin: {
description: 'Persönlicher Termin. null wenn keiner im Brief steht.',
anyOf: [
{
type: 'object', additionalProperties: false, required: ['datum', 'uhrzeit', 'ort'],
properties: {
datum: { type: 'string', description: 'ISO JJJJ-MM-TT' },
uhrzeit: { anyOf: [{ type: 'string' }, { type: 'null' }] },
ort: { anyOf: [{ type: 'string' }, { type: 'null' }] },
},
},
{ type: 'null' },
],
},
checkliste: { type: 'array', description: 'To-do-Liste. Leer wenn nichts zu tun ist.', items: { type: 'string' } },
},
};
function demoCorsHeaders(origin: string | null): Record<string, string> {
const erlaubt = origin && DEMO_ORIGIN_MUSTER.test(origin) ? origin : 'https://behoerdenklar.pages.dev';
return {
'access-control-allow-origin': erlaubt,
'access-control-allow-methods': 'POST, OPTIONS',
'access-control-allow-headers': 'content-type',
'access-control-max-age': '86400',
};
}
/** Fehler für die Demo-Seite: { code, meldung } + CORS. */
function demoFehler(status: number, code: string, meldung: string, origin: string | null): Response {
return Response.json({ code, meldung }, { status, headers: demoCorsHeaders(origin) });
}
/** SHA-256-Hash der E-Mail (mit Pepper) — es wird nie Klartext gespeichert. */
async function emailHash(email: string, pepper: string): Promise<string> {
const daten = new TextEncoder().encode(`bk-demo|${pepper}|${email}`);
const digest = await crypto.subtle.digest('SHA-256', daten);
return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');
}
async function demoHandler(request: Request, env: Env): Promise<Response> {
const origin = request.headers.get('origin');
if (request.method === 'OPTIONS') {
return new Response(null, { status: 204, headers: demoCorsHeaders(origin) });
}
if (request.method !== 'POST') {
return demoFehler(405, 'methode', 'Nur POST erlaubt.', origin);
}
if (!origin || !DEMO_ORIGIN_MUSTER.test(origin)) {
return demoFehler(403, 'origin', 'Aufruf nur von der BehördenKlar-Webseite erlaubt.', origin);
}
let body: { bild?: string; mimeType?: string; turnstileToken?: string; email?: string };
try {
body = await request.json();
} catch {
return demoFehler(400, 'json', 'Ungültige Anfrage.', origin);
}
const { bild, mimeType, turnstileToken } = body;
const email = typeof body.email === 'string' ? body.email.trim().toLowerCase() : null;
if (typeof bild !== 'string' || bild.length === 0 || bild.length > DEMO_MAX_BASE64) {
return demoFehler(400, 'datei', 'Die Datei fehlt oder ist zu groß (max. 5 MB).', origin);
}
if (mimeType !== 'image/jpeg' && mimeType !== 'image/png' && mimeType !== 'application/pdf') {
return demoFehler(400, 'datei', 'Nur Fotos (JPG/PNG) oder PDF sind möglich.', origin);
}
if (typeof turnstileToken !== 'string' || !turnstileToken) {
return demoFehler(403, 'turnstile', 'Sicherheitsprüfung fehlt. Bitte Seite neu laden.', origin);
}
// Schicht 1: Turnstile serverseitig verifizieren (niemals nur im Browser!)
const ip = request.headers.get('cf-connecting-ip') ?? 'unbekannt';
const pruefung = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ secret: env.TURNSTILE_SECRET_KEY, response: turnstileToken, remoteip: ip }),
});
const pruefungJson = (await pruefung.json()) as { success?: boolean };
if (!pruefungJson.success) {
return demoFehler(403, 'turnstile', 'Sicherheitsprüfung fehlgeschlagen. Bitte Seite neu laden und erneut versuchen.', origin);
}
// E-Mail prüfen (nur für die 2. Analyse nötig)
let mailKey: string | null = null;
if (email) {
if (!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email)) {
return demoFehler(400, 'email', 'Bitte geben Sie eine gültige E-Mail-Adresse ein.', origin);
}
const domain = email.split('@')[1];
if (WEGWERF_DOMAINS.has(domain)) {
return demoFehler(400, 'email', 'Wegwerf-E-Mail-Adressen sind nicht möglich. Bitte nutzen Sie Ihre normale Adresse.', origin);
}
mailKey = `demo:mail:${await emailHash(email, env.TURNSTILE_SECRET_KEY)}`;
}
// Schichten 2-5: Limits lesen. IP- und Anon-Zähler sind bewusst TÄGLICH
// (Datum im Schlüssel): Ein Anschluss, den sich mehrere Menschen teilen
// (Familie, WLAN, Mobilfunk/CGNAT), darf pro Tag mehrere erste Analysen
// machen. Sonst würde der zweite Besucher an derselben Leitung sofort zur
// E-Mail gezwungen. Die eigentliche "2 pro Person"-Grenze setzt der
// Browser (localStorage) + der E-Mail-Hash; IP ist nur ein Missbrauchs-Damm.
const heute = new Date().toISOString().slice(0, 10);
const tagKey = `demo:tag:${heute}`;
const ipKey = `demo:ip:${ip}:${heute}`;
const anonKey = `demo:anon:${ip}:${heute}`;
const budget = parseInt(env.DEMO_TAGES_BUDGET || '100', 10);
const ipLimit = parseInt(env.DEMO_LIMIT_IP || '8', 10);
// Wie viele anonyme (ohne E-Mail) Analysen ein Anschluss pro Tag darf,
// bevor eine E-Mail nötig wird — großzügig, damit geteilte Leitungen gehen.
const ANON_PRO_IP = 3;
const [tagWert, ipWert, anonWert, mailWert] = await Promise.all([
env.RATE_LIMIT.get(tagKey),
env.RATE_LIMIT.get(ipKey),
env.RATE_LIMIT.get(anonKey),
mailKey ? env.RATE_LIMIT.get(mailKey) : Promise.resolve(null),
]);
const tagZahl = parseInt(tagWert ?? '0', 10);
const ipZahl = parseInt(ipWert ?? '0', 10);
const anonZahl = parseInt(anonWert ?? '0', 10);
// Schicht 5: globales Tagesbudget (Kosten-Deckel)
if (tagZahl >= budget) {
return demoFehler(429, 'budget', 'Die Gratis-Demo ist für heute ausgebucht. Kommen Sie morgen wieder — oder tragen Sie sich in die Warteliste ein.', origin);
}
// Schicht 4: IP-Gesamtlimit pro Tag (Missbrauchs-Damm, großzügig)
if (ipZahl >= ipLimit) {
return demoFehler(429, 'aufgebraucht', 'Für heute wurden über diesen Anschluss viele Gratis-Analysen genutzt. Kommen Sie morgen wieder — oder holen Sie sich die App.', origin);
}
// Schicht 2/3: nach mehreren anonymen Analysen pro Anschluss E-Mail nötig;
// pro E-Mail dauerhaft nur 1x
if (!email && anonZahl >= ANON_PRO_IP) {
return demoFehler(403, 'email_noetig', 'Für weitere Gratis-Analysen über diesen Anschluss geben Sie bitte Ihre E-Mail-Adresse ein.', origin);
}
if (mailKey && mailWert !== null) {
return demoFehler(429, 'aufgebraucht', 'Mit dieser E-Mail-Adresse wurde die Gratis-Analyse schon genutzt. In der App gibt es 3 weitere gratis.', origin);
}
// KI-Analyse — identischer Aufbau wie in der App
const dateiBlock =
mimeType === 'application/pdf'
? { type: 'document', source: { type: 'base64', media_type: 'application/pdf', data: bild } }
: { type: 'image', source: { type: 'base64', media_type: mimeType, data: bild } };
const antwort = await fetch(ANTHROPIC_URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-api-key': env.ANTHROPIC_API_KEY,
'anthropic-version': ANTHROPIC_VERSION,
},
body: JSON.stringify({
model: 'claude-sonnet-5',
max_tokens: MAX_TOKENS_OBERGRENZE,
system: DEMO_SYSTEM_PROMPT,
output_config: { format: { type: 'json_schema', schema: DEMO_SCHEMA } },
messages: [
{
role: 'user',
content: [
dateiBlock,
{ type: 'text', text: `Analysiere diesen Behördenbrief. Heute ist der ${heute} (wichtig für relative Datumsangaben wie "innerhalb von 14 Tagen").` },
],
},
],
}),
});
if (!antwort.ok) {
const status = antwort.status;
// Fehlerdetails ins Worker-Log (wrangler tail) — hilft bei der Diagnose
console.log('Demo-KI-Fehler', status, (await antwort.text()).slice(0, 500));
if (status === 429 || status >= 500) {
return demoFehler(503, 'ki', 'Der KI-Dienst ist gerade ausgelastet. Bitte versuchen Sie es in einer Minute erneut.', origin);
}
return demoFehler(502, 'ki', 'Die Analyse ist fehlgeschlagen. Bitte versuchen Sie es mit einem neuen, gut beleuchteten Foto.', origin);
}
const daten = (await antwort.json()) as {
stop_reason?: string;
content?: { type: string; text?: string }[];
};
// Erst NACH erfolgreichem KI-Aufruf zählen (Fehler kosten kein Kontingent).
// Tag-, IP- und Anon-Zähler laufen nach 48h ab (sie sind tagesbasiert).
const TAG_TTL = 60 * 60 * 48;
const schreiben: Promise<void>[] = [
env.RATE_LIMIT.put(tagKey, String(tagZahl + 1), { expirationTtl: TAG_TTL }),
env.RATE_LIMIT.put(ipKey, String(ipZahl + 1), { expirationTtl: TAG_TTL }),
];
if (!email) {
schreiben.push(env.RATE_LIMIT.put(anonKey, String(anonZahl + 1), { expirationTtl: TAG_TTL }));
}
if (mailKey) {
// bewusst OHNE TTL: „pro E-Mail für immer nur 1" — es liegt nur der Hash
schreiben.push(env.RATE_LIMIT.put(mailKey, heute));
}
await Promise.all(schreiben);
if (daten.stop_reason === 'refusal') {
return demoFehler(422, 'inhalt', 'Die KI konnte diesen Inhalt nicht verarbeiten. Bitte prüfen Sie, ob das Foto wirklich einen Behördenbrief zeigt.', origin);
}
const textBlock = [...(daten.content ?? [])].reverse().find((b) => b.type === 'text');
if (!textBlock?.text) {
return demoFehler(502, 'ki', 'Die KI hat keine verwertbare Antwort geliefert. Bitte erneut versuchen.', origin);
}
let analyse: unknown;
try {
analyse = JSON.parse(textBlock.text);
} catch {
return demoFehler(502, 'ki', 'Die Antwort war unlesbar. Bitte erneut versuchen.', origin);
}
return Response.json(
{ analyse, versuch: email ? 2 : 1 },
{ headers: demoCorsHeaders(origin) }
);
}
export default { export default {
async fetch(request: Request, env: Env): Promise<Response> { async fetch(request: Request, env: Env): Promise<Response> {
// Web-Demo hat einen eigenen Pfad mit eigenen Regeln
if (new URL(request.url).pathname === '/demo') {
return demoHandler(request, env);
}
if (request.method !== 'POST') { if (request.method !== 'POST') {
return fehler(405, 'invalid_request_error', 'Nur POST erlaubt.'); return fehler(405, 'invalid_request_error', 'Nur POST erlaubt.');
} }

View File

@@ -8,6 +8,12 @@ compatibility_date = "2026-07-01"
[vars] [vars]
TAGES_LIMIT = "20" TAGES_LIMIT = "20"
TAGES_LIMIT_IP = "100" TAGES_LIMIT_IP = "100"
# Web-Demo (/demo): hartes Tagesbudget über alle Nutzer (Kosten-Deckel,
# 100 Analysen ≈ 2,50 €/Tag Maximalschaden) + IP-Gesamtlimit PRO TAG
# (großzügig, damit geteilte Anschlüsse/Familien/Mobilfunk nicht blockiert
# werden; der Missbrauch wird zusätzlich durch Turnstile + Budget begrenzt)
DEMO_TAGES_BUDGET = "100"
DEMO_LIMIT_IP = "8"
[[kv_namespaces]] [[kv_namespaces]]
binding = "RATE_LIMIT" binding = "RATE_LIMIT"

View File

@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/ar">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="ar_AR">
<meta property="og:url" content="https://behoerdenklar.pages.dev/ar">
<meta property="og:title" content="وصلتك رسالة من دائرة حكومية ألمانية؟">
<meta property="og:description" content="صوّر الرسالة — التطبيق يشرحها بالعربية وبلغة بسيطة ويحدد المواعيد المهمة. سجّل في قائمة الانتظار: 5 تحليلات مجانية.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d; --papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d;
@@ -128,6 +142,15 @@
margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte); margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte);
font-size: 14.5px; color: var(--grau); font-size: 14.5px; color: var(--grau);
} }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
</head> </head>
<body> <body>
@@ -209,9 +232,13 @@
🎁 <strong>هديتك:</strong> حلّل <strong>٥ رسائل مجاناً</strong> 🎁 <strong>هديتك:</strong> حلّل <strong>٥ رسائل مجاناً</strong>
بدلاً من ٣. تحصل على الرمز عبر البريد الإلكتروني. بدلاً من ٣. تحصل على الرمز عبر البريد الإلكتروني.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste%20(Arabisch)&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist.%20%2F%20Please%20notify%20me%20when%20Beh%C3%B6rdenKlar%20is%20available."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 سجّل عبر البريد الإلكتروني <input class="wl-input" type="email" name="EMAIL" placeholder="بريدك الإلكتروني" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">سجّل في قائمة الانتظار ←</button>
</form>
<p class="klein"> <p class="klein">
نحفظ عنوان بريدك الإلكتروني فقط لهذه الرسالة الواحدة. يمكنك إلغاء نحفظ عنوان بريدك الإلكتروني فقط لهذه الرسالة الواحدة. يمكنك إلغاء
التسجيل في أي وقت. <a href="datenschutz.html">سياسة الخصوصية (بالألمانية)</a>. التسجيل في أي وقت. <a href="datenschutz.html">سياسة الخصوصية (بالألمانية)</a>.
@@ -226,6 +253,6 @@
</footer> </footer>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

View File

@@ -145,7 +145,38 @@
Ihre Adresse wird dann gelöscht. Ihre Adresse wird dann gelöscht.
</p> </p>
<h2>8. Reichweitenmessung (Webseite)</h2> <h2>8. Gratis-Demo (Webseite)</h2>
<p>
Auf unserer Webseite können Sie zwei Brief-Analysen kostenlos
ausprobieren, ohne die App zu installieren. Dabei gilt:
</p>
<ul>
<li>
<strong>Ihr Brief-Foto</strong> wird — nur mit Ihrer Einwilligung
(Häkchen vor dem Hochladen, Art. 6 Abs. 1 lit. a, Art. 9 Abs. 2
lit. a DSGVO) — über unseren Server (Cloudflare) an Anthropic (USA)
zur Analyse geschickt. Es wird auf unserem Server nicht gespeichert;
bei Anthropic wird es nach spätestens 30 Tagen gelöscht (wie in
Abschnitt 3a beschrieben). Das Ergebnis sehen nur Sie in Ihrem
Browser; wir speichern es nicht.
</li>
<li>
<strong>Zum Schutz vor Missbrauch</strong> (Art. 6 Abs. 1 lit. f
DSGVO) prüfen wir Anfragen mit Cloudflare Turnstile (Bot-Erkennung
durch Cloudflare, Inc., USA), zählen Analysen pro IP-Adresse
(Speicherung max. 30 Tage) und führen ein tägliches Gesamtlimit.
</li>
<li>
<strong>Für die zweite Gratis-Analyse</strong> geben Sie Ihre
E-Mail-Adresse an. Wir speichern sie ausschließlich als
nicht umkehrbare Prüfsumme (Hash), um das Kontingent von zwei
Analysen durchzusetzen — die Adresse selbst wird nicht gespeichert
und nicht für E-Mails verwendet. In die Warteliste (Abschnitt 7)
kommen Sie nur, wenn Sie sich dort separat eintragen.
</li>
</ul>
<h2>9. Reichweitenmessung (Webseite)</h2>
<p> <p>
Auf dieser Webseite nutzen wir Cloudflare Web Analytics (Cloudflare, Auf dieser Webseite nutzen wir Cloudflare Web Analytics (Cloudflare,
Inc., USA) — eine datenschutzfreundliche Besucherstatistik Inc., USA) — eine datenschutzfreundliche Besucherstatistik
@@ -157,14 +188,14 @@
DSGVO). DSGVO).
</p> </p>
<h2>9. Keine Rechtsberatung</h2> <h2>10. Keine Rechtsberatung</h2>
<p> <p>
BehördenKlar erklärt Briefe verständlich, ersetzt aber keine BehördenKlar erklärt Briefe verständlich, ersetzt aber keine
Rechtsberatung. Bei rechtlich wichtigen Entscheidungen wenden Sie sich Rechtsberatung. Bei rechtlich wichtigen Entscheidungen wenden Sie sich
an eine Beratungsstelle oder eine Anwältin/einen Anwalt. an eine Beratungsstelle oder eine Anwältin/einen Anwalt.
</p> </p>
<h2>10. Änderungen</h2> <h2>11. Änderungen</h2>
<p> <p>
Wir passen diese Datenschutzerklärung an, wenn sich die App oder die Wir passen diese Datenschutzerklärung an, wenn sich die App oder die
Rechtslage ändert. Die aktuelle Fassung finden Sie immer auf dieser Rechtslage ändert. Die aktuelle Fassung finden Sie immer auf dieser
@@ -175,6 +206,6 @@
<a class="zurueck" href="index.html">← Zurück zur Startseite</a> <a class="zurueck" href="index.html">← Zurück zur Startseite</a>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

556
webseite/demo.html Normal file
View File

@@ -0,0 +1,556 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gratis-Demo: Behördenbrief online erklären lassen | BehördenKlar</title>
<meta name="description" content="Testen Sie BehördenKlar direkt im Browser: Brief fotografieren, hochladen, in einfacher Sprache erklärt bekommen. 2 Analysen gratis, ohne Konto.">
<link rel="canonical" href="https://behoerdenklar.pages.dev/demo">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.pages.dev/demo">
<meta property="og:title" content="Probieren Sie es aus: Ihr Behördenbrief, einfach erklärt">
<meta property="og:description" content="Direkt im Browser testen — 2 Gratis-Analysen, ohne Konto. Brief fotografieren, Klartext lesen.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<style>
:root {
--papier: #faf7f0;
--papier-dunkel: #f1ecdf;
--tinte: #21211d;
--grau: #6b675e;
--amtsblau: #1d4e89;
--stempelrot: #b3372b;
--marker: #ffe66b;
--gruen: #2e7d4f;
--rot: #b3372b;
--gelb: #a06b00;
color-scheme: light;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
font-family: Georgia, 'Times New Roman', serif;
background:
repeating-linear-gradient(0deg, transparent 0 34px, rgba(33, 33, 29, 0.025) 34px 35px),
var(--papier);
color: var(--tinte);
line-height: 1.7;
font-size: 17px;
}
.mono { font-family: 'Courier New', ui-monospace, monospace; letter-spacing: 0.02em; }
.wrap { max-width: 720px; margin: 0 auto; padding: 0 20px 72px; }
.briefkopf {
display: flex; justify-content: space-between; align-items: baseline;
padding: 20px 0 12px; border-bottom: 2px solid var(--tinte);
font-size: 14px;
}
.briefkopf .absender { font-weight: 700; font-size: 16px; }
.briefkopf .absender a { color: inherit; text-decoration: none; }
.briefkopf .az { color: var(--grau); font-size: 13px; }
header { padding: 40px 0 8px; }
.betreff-label {
font-size: 13px; color: var(--grau); text-transform: uppercase;
letter-spacing: 0.14em; margin-bottom: 10px;
}
h1 {
font-size: clamp(30px, 6vw, 44px);
line-height: 1.15; font-weight: 700; letter-spacing: -0.01em;
}
.markiert {
background: linear-gradient(104deg, transparent 2%, var(--marker) 4%, var(--marker) 96%, transparent 98%);
padding: 0 6px; box-decoration-break: clone; -webkit-box-decoration-break: clone;
}
.anrede { margin-top: 20px; font-size: 18px; max-width: 580px; }
section { margin-top: 44px; }
h2 {
font-size: 15px; text-transform: uppercase; letter-spacing: 0.14em;
color: var(--grau); font-weight: 400; margin-bottom: 20px;
display: flex; align-items: center; gap: 12px;
}
h2::after { content: ''; flex: 1; border-top: 1px solid rgba(33,33,29,0.25); }
h2 .nr { font-family: 'Courier New', ui-monospace, monospace; }
.antrag {
background: #fff; border: 2px solid var(--tinte);
box-shadow: 7px 8px 0 rgba(33, 33, 29, 0.9);
padding: 28px 26px; position: relative;
}
.formular-kopf {
font-family: 'Courier New', ui-monospace, monospace;
font-size: 13px; text-transform: uppercase; letter-spacing: 0.1em;
color: var(--grau); margin-bottom: 10px;
}
.cta {
display: inline-block; width: 100%; padding: 17px 30px;
background: var(--amtsblau); color: #fff; text-decoration: none;
font-family: inherit; font-size: 18px; font-weight: 700; text-align: center;
border: 2px solid var(--tinte);
box-shadow: 5px 5px 0 var(--tinte);
transition: transform 0.12s ease, box-shadow 0.12s ease;
cursor: pointer;
}
.cta:hover:not(:disabled) { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--tinte); }
.cta:disabled { opacity: 0.45; cursor: not-allowed; }
.konsens {
display: flex; gap: 12px; align-items: flex-start;
font-size: 15px; color: var(--grau); margin: 14px 0 18px;
}
.konsens input { width: 22px; height: 22px; margin-top: 4px; flex-shrink: 0; accent-color: var(--amtsblau); }
.konsens a { color: var(--amtsblau); }
.klein { font-size: 13.5px; color: var(--grau); margin-top: 12px; }
.klein a { color: var(--grau); }
.status { text-align: center; padding: 26px 10px; display: none; }
.status .gross { font-size: 20px; font-weight: 700; }
.status .sub { color: var(--grau); margin-top: 6px; font-size: 15px; }
.sanduhr {
display: inline-block; font-size: 34px;
animation: drehen 2.4s linear infinite;
}
@keyframes drehen { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.fehlerbox {
display: none; margin-top: 16px;
border: 2px solid var(--stempelrot); background: #fdf1ef;
color: #7c2018; padding: 14px 16px; font-size: 16px;
}
.email-teil { display: none; margin-top: 16px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
margin-bottom: 12px;
}
.wl-input::placeholder { color: #9a958a; }
/* Ergebnis */
#ergebnis { display: none; }
.brief-karte {
background: #fff; border: 1px solid rgba(33, 33, 29, 0.28);
padding: 22px 24px; position: relative; margin-top: 22px;
box-shadow: 4px 5px 0 rgba(33, 33, 29, 0.08);
}
.karten-label {
position: absolute; top: -12px; left: 16px;
font-family: 'Courier New', ui-monospace, monospace; font-size: 12px;
text-transform: uppercase; letter-spacing: 0.1em;
background: var(--gruen); color: var(--papier); padding: 3px 10px;
}
.karten-label.neutral { background: var(--tinte); }
.ampelzeile {
margin-top: 14px; padding-top: 12px;
border-top: 1px dashed rgba(33, 33, 29, 0.3);
font-size: 16px; font-weight: 700;
}
.todo { padding: 8px 0 8px 2px; border-bottom: 1px dotted rgba(33,33,29,0.3); font-size: 16.5px; }
.todo::before { content: '☐'; margin-right: 10px; color: var(--amtsblau); font-size: 18px; }
details { border-bottom: 1px solid rgba(33, 33, 29, 0.2); padding: 12px 4px; }
summary { font-weight: 700; cursor: pointer; font-size: 16.5px; list-style: none; }
summary::-webkit-details-marker { display: none; }
details p { margin-top: 8px; color: var(--grau); font-size: 15.5px; }
.stempel {
display: inline-block; padding: 7px 14px;
border: 2.5px solid var(--stempelrot); color: var(--stempelrot);
font-family: 'Courier New', ui-monospace, monospace; font-weight: 700;
font-size: 14px; letter-spacing: 0.1em; text-transform: uppercase;
transform: rotate(-4deg); opacity: 0.9;
}
.hinweis-recht {
margin-top: 18px; font-size: 14px; color: var(--grau);
border-top: 1px dashed rgba(33,33,29,0.3); padding-top: 12px;
}
/* Warteliste-Formular (wie Startseite) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.bonus-zeile {
margin: 14px 0; padding: 12px 16px;
background: linear-gradient(104deg, transparent 1%, var(--marker) 3%, var(--marker) 97%, transparent 99%);
font-size: 16px;
}
footer { margin-top: 48px; font-size: 14.5px; color: var(--grau); }
footer a { color: var(--grau); }
</style>
</head>
<body>
<div class="wrap">
<div class="briefkopf">
<span class="absender"><a href="index.html">📬 BehördenKlar</a></span>
<span class="az mono">Formular D-01 · Gratis-Demo</span>
</div>
<header>
<p class="betreff-label">Betreff</p>
<h1>Probieren Sie es aus —<br><span class="markiert">mit Ihrem eigenen Brief.</span></h1>
<p class="anrede">
Kein Konto. Keine App-Installation. Laden Sie ein Foto Ihres
Behördenbriefs hoch — in etwa einer Minute lesen Sie ihn in einfacher
Sprache. <strong>2 Analysen gratis.</strong>
</p>
</header>
<section id="demo">
<h2><span class="nr">§ 1</span> Brief hochladen</h2>
<div class="antrag">
<p class="formular-kopf">Antrag auf Klartext · 2 Gratis-Analysen</p>
<div id="eingabe">
<label class="konsens">
<input type="checkbox" id="konsens">
<span>
Ich bin einverstanden, dass mein Brief-Foto zur Analyse an den
Server von BehördenKlar und an den KI-Dienst Anthropic (USA)
geschickt wird. Es wird dort nicht dauerhaft gespeichert.
Behördenbriefe enthalten persönliche Daten — laden Sie nur hoch,
was Sie analysieren lassen möchten.
<a href="datenschutz.html" target="_blank">Datenschutzerklärung</a>
</span>
</label>
<div id="emailTeil" class="email-teil">
<p style="margin-bottom: 10px;">
🎉 <strong>Ihre erste Analyse ist verbraucht.</strong> Für die
zweite geben Sie bitte Ihre E-Mail-Adresse ein — so stellen wir
sicher, dass jeder genau 2 Gratis-Analysen bekommt.
</p>
<input class="wl-input" type="email" id="email" placeholder="Ihre E-Mail-Adresse" autocomplete="email">
<p class="klein" style="margin: 0 0 12px;">
Die Adresse wird nur verschlüsselt (als Prüfsumme) gespeichert,
um mitzuzählen — Sie bekommen dadurch keine E-Mails von uns.
</p>
</div>
<input type="file" id="datei" accept="image/jpeg,image/png,application/pdf" style="display: none;">
<button class="cta" id="startKnopf" disabled>📷 Brief auswählen &amp; erklären lassen</button>
<div class="cf-turnstile" data-sitekey="0x4AAAAAAD8vfEq7X2EX-Krk" data-action="turnstile-spin-v1" style="margin-top: 14px;"></div>
<p class="klein">
Geht mit Foto (JPG/PNG) oder PDF, max. 5 MB. Tipp: gutes Licht,
Brief von oben, ganzer Text im Bild.
</p>
</div>
<div class="status" id="status">
<span class="sanduhr"></span>
<p class="gross">Ihr Brief wird analysiert…</p>
<p class="sub">Das dauert bis zu einer Minute. Bitte lassen Sie die Seite geöffnet.</p>
</div>
<div class="fehlerbox" id="fehler"></div>
</div>
</section>
<section id="ergebnis">
<h2><span class="nr">§ 2</span> Ihr Brief in Klartext</h2>
<div class="brief-karte">
<span class="karten-label neutral" id="ergBrieftyp">Brief</span>
<p style="margin-top: 6px;"><strong id="ergKern"></strong></p>
<p class="ampelzeile" id="ergAmpel" style="display: none;"></p>
</div>
<div class="brief-karte">
<span class="karten-label">Einfach erklärt</span>
<p id="ergErklaerung" style="white-space: pre-line;"></p>
</div>
<div class="brief-karte" id="ergChecklisteKarte" style="display: none;">
<span class="karten-label neutral">Das müssen Sie tun</span>
<div id="ergCheckliste"></div>
</div>
<div class="brief-karte" id="ergBegriffeKarte" style="display: none;">
<span class="karten-label neutral">Schwere Wörter erklärt</span>
<div id="ergBegriffe"></div>
</div>
<p class="hinweis-recht">
⚖️ BehördenKlar erklärt Briefe, ersetzt aber keine Rechtsberatung. Bei
wichtigen Entscheidungen hilft eine Beratungsstelle oder ein Anwalt.
</p>
</section>
<section id="werbung" style="display: none;">
<h2><span class="nr">§ 3</span> Wie geht es weiter?</h2>
<div class="antrag">
<p class="formular-kopf" id="restZeile">Warteliste</p>
<h3 id="wlTitel" style="font-size: 24px; line-height: 1.3;">Das hat Ihnen geholfen?</h3>
<p style="margin-top: 10px;">
Die App kann noch mehr: Briefe <strong>übersetzen in 9 Sprachen</strong>,
Fristen mit <strong>Erinnerung</strong>, fertige
<strong>Antwort-Entwürfe</strong> — und Ihre Briefe bleiben
verschlüsselt auf Ihrem Handy gespeichert.
</p>
<p class="bonus-zeile">
🎁 Warteliste = <strong>5 Gratis-Analysen</strong> in der App statt 3.
</p>
<p id="nochmalZeile" style="display: none; margin-bottom: 14px;">
<a href="#demo" style="color: var(--amtsblau); font-weight: 700;">↑ Noch einen
Brief testen? Ihre zweite Gratis-Analyse wartet oben.</a>
</p>
<form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
<input class="wl-input" style="margin-bottom: 0;" type="email" name="EMAIL" id="wlEmail" placeholder="Ihre E-Mail-Adresse" required autocomplete="email">
<input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta" type="submit">Auf die Warteliste eintragen →</button>
</form>
<p class="klein">
Eine E-Mail zum Start, keine Werbung, jederzeit abmeldbar —
<a href="datenschutz.html">Datenschutzerklärung</a>.
</p>
<div style="margin-top: 16px;"><span class="stempel">Bald im App Store</span></div>
</div>
</section>
<footer>
<a href="index.html">← Zur Startseite</a> ·
<a href="impressum.html">Impressum</a> ·
<a href="datenschutz.html">Datenschutzerklärung</a>
</footer>
</div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<script>
(function () {
'use strict';
var ENDPUNKT = 'https://behoerdenklar-proxy.behoerdenbrief.workers.dev/demo';
var MAX_KANTE = 2000; // wie in der App: reicht für A4, spart Datenvolumen
var konsens = document.getElementById('konsens');
var startKnopf = document.getElementById('startKnopf');
var dateiFeld = document.getElementById('datei');
var emailTeil = document.getElementById('emailTeil');
var emailFeld = document.getElementById('email');
var status = document.getElementById('status');
var eingabe = document.getElementById('eingabe');
var fehlerBox = document.getElementById('fehler');
// Schlüsselname bewusst 'v2': setzt evtl. falsch gezählte Stände (aus der
// Testphase) bei bestehenden Besuchern automatisch einmalig zurück.
var SPEICHER_SCHLUESSEL = 'bk_demo_v2';
function benutzt() { return parseInt(localStorage.getItem(SPEICHER_SCHLUESSEL) || '0', 10); }
function setzeBenutzt(n) { localStorage.setItem(SPEICHER_SCHLUESSEL, String(n)); }
function zeigeStand() {
// 2. Versuch: E-Mail-Feld einblenden; alles verbraucht: Eingabe sperren
if (benutzt() >= 2) {
eingabe.style.display = 'none';
fehlerBox.style.display = 'block';
fehlerBox.innerHTML = 'Ihre 2 Gratis-Analysen sind verbraucht. 🎁 In der <strong>App</strong> gibt es 3 weitere gratis — mit Warteliste sogar 5. Tragen Sie sich unten ein!';
document.getElementById('werbung').style.display = 'block';
} else if (benutzt() === 1) {
emailTeil.style.display = 'block';
}
}
konsens.addEventListener('change', function () { startKnopf.disabled = !konsens.checked; });
startKnopf.addEventListener('click', function () {
fehlerBox.style.display = 'none';
if (benutzt() >= 1 && !emailFeld.value.trim()) {
emailTeil.style.display = 'block';
emailFeld.focus();
zeigeFehler('Bitte geben Sie zuerst Ihre E-Mail-Adresse ein — dann wählen Sie den Brief aus.');
return;
}
dateiFeld.click();
});
dateiFeld.addEventListener('change', function () {
if (dateiFeld.files && dateiFeld.files[0]) starteAnalyse(dateiFeld.files[0]);
});
function zeigeFehler(text) {
fehlerBox.style.display = 'block';
fehlerBox.textContent = text;
}
function turnstileToken() {
var feld = document.querySelector('[name="cf-turnstile-response"]');
return feld ? feld.value : '';
}
/** Foto verkleinern (max 2000px, JPEG 60%) — wie in der App. */
function bildVerkleinern(datei) {
return new Promise(function (resolve, reject) {
var img = new Image();
var url = URL.createObjectURL(datei);
img.onload = function () {
URL.revokeObjectURL(url);
var f = Math.min(1, MAX_KANTE / Math.max(img.width, img.height));
var c = document.createElement('canvas');
c.width = Math.round(img.width * f);
c.height = Math.round(img.height * f);
c.getContext('2d').drawImage(img, 0, 0, c.width, c.height);
resolve(c.toDataURL('image/jpeg', 0.6).split(',')[1]);
};
img.onerror = function () { URL.revokeObjectURL(url); reject(new Error('Bild unlesbar')); };
img.src = url;
});
}
function pdfAlsBase64(datei) {
return new Promise(function (resolve, reject) {
var leser = new FileReader();
leser.onload = function () { resolve(String(leser.result).split(',')[1]); };
leser.onerror = function () { reject(new Error('Datei unlesbar')); };
leser.readAsDataURL(datei);
});
}
async function starteAnalyse(datei) {
fehlerBox.style.display = 'none';
if (datei.size > 5 * 1024 * 1024 && datei.type === 'application/pdf') {
zeigeFehler('Die PDF-Datei ist zu groß (max. 5 MB). Tipp: Fotografieren Sie den Brief stattdessen.');
return;
}
var token = turnstileToken();
if (!token) {
zeigeFehler('Die Sicherheitsprüfung lädt noch — bitte warten Sie 2 Sekunden und versuchen Sie es erneut.');
return;
}
eingabe.style.display = 'none';
status.style.display = 'block';
try {
var istPdf = datei.type === 'application/pdf';
var base64 = istPdf ? await pdfAlsBase64(datei) : await bildVerkleinern(datei);
var body = {
bild: base64,
mimeType: istPdf ? 'application/pdf' : 'image/jpeg',
turnstileToken: token,
};
var email = emailFeld.value.trim();
if (benutzt() >= 1 && email) body.email = email;
var antwort = await fetch(ENDPUNKT, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
});
var daten = await antwort.json();
if (!antwort.ok) {
status.style.display = 'none';
eingabe.style.display = 'block';
if (window.turnstile) window.turnstile.reset();
if (daten.code === 'email_noetig') {
// Nur das E-Mail-Feld zeigen — NICHT als verbraucht markieren.
// (Sonst würde ein serverseitiges "E-Mail nötig", z. B. bei
// geteiltem Anschluss, den Browser dauerhaft blockieren, obwohl
// gar keine Analyse gelungen ist.)
emailTeil.style.display = 'block';
emailFeld.focus();
}
if (daten.code === 'aufgebraucht') {
setzeBenutzt(2);
zeigeStand();
return;
}
zeigeFehler(daten.meldung || 'Etwas ist schiefgelaufen. Bitte erneut versuchen.');
return;
}
setzeBenutzt(Math.max(benutzt(), daten.versuch));
if (email) document.getElementById('wlEmail').value = email;
// Token erneuern — sonst würde die 2. Analyse ein "Seite neu laden" verlangen
if (window.turnstile) window.turnstile.reset();
zeigeErgebnis(daten.analyse, daten.versuch);
} catch (e) {
status.style.display = 'none';
eingabe.style.display = 'block';
if (window.turnstile) window.turnstile.reset();
zeigeFehler('Verbindung fehlgeschlagen. Bitte prüfen Sie Ihr Internet und versuchen Sie es erneut.');
}
}
/** Ampel wie in der App: rot ≤ 7 Tage, gelb ≤ 21, sonst grün. */
function ampel(analyse) {
var daten = [];
if (analyse.frist && analyse.frist.datum) daten.push(analyse.frist.datum);
if (analyse.termin && analyse.termin.datum) daten.push(analyse.termin.datum);
if (!daten.length) return null;
daten.sort();
var tage = Math.ceil((new Date(daten[0] + 'T12:00:00') - new Date()) / 86400000);
if (isNaN(tage)) return null;
var farbe = tage <= 7 ? 'var(--rot)' : tage <= 21 ? 'var(--gelb)' : 'var(--gruen)';
var punkt = tage <= 7 ? '🔴' : tage <= 21 ? '🟡' : '🟢';
var text = tage < 0 ? 'Die Frist ist womöglich schon vorbei!' :
tage === 0 ? 'HEUTE ist der wichtige Tag!' :
'Noch ' + tage + ' Tage Zeit (' + daten[0].split('-').reverse().join('.') + ')';
return { farbe: farbe, text: punkt + ' ' + text };
}
function zeigeErgebnis(analyse, versuch) {
status.style.display = 'none';
document.getElementById('ergBrieftyp').textContent = analyse.brieftyp || 'Ihr Brief';
document.getElementById('ergKern').textContent = analyse.kernaussage || '';
document.getElementById('ergErklaerung').textContent = analyse.erklaerung_einfach || '';
var a = ampel(analyse);
var ampelEl = document.getElementById('ergAmpel');
if (a) {
ampelEl.style.display = 'block';
ampelEl.style.color = a.farbe;
var teile = [a.text];
if (analyse.frist && analyse.frist.aktion) teile.push(analyse.frist.aktion);
ampelEl.textContent = teile.join(' · ');
}
if (analyse.checkliste && analyse.checkliste.length) {
document.getElementById('ergChecklisteKarte').style.display = 'block';
document.getElementById('ergCheckliste').innerHTML = analyse.checkliste
.map(function (t) { var d = document.createElement('div'); d.className = 'todo'; d.textContent = t; return d.outerHTML; })
.join('');
}
if (analyse.fachbegriffe && analyse.fachbegriffe.length) {
document.getElementById('ergBegriffeKarte').style.display = 'block';
document.getElementById('ergBegriffe').innerHTML = analyse.fachbegriffe
.map(function (b) {
var det = document.createElement('details');
var sum = document.createElement('summary');
sum.textContent = b.begriff;
var p = document.createElement('p');
p.textContent = b.erklaerung;
det.appendChild(sum); det.appendChild(p);
return det.outerHTML;
})
.join('');
}
document.getElementById('ergebnis').style.display = 'block';
var rest = 2 - benutzt();
document.getElementById('restZeile').textContent =
rest > 0 ? 'Noch ' + rest + ' Gratis-Analyse übrig' : 'Ihre 2 Gratis-Analysen sind verbraucht';
document.getElementById('wlTitel').textContent =
rest > 0 ? 'Das hat Ihnen geholfen?' : 'Weiter geht es in der App';
document.getElementById('werbung').style.display = 'block';
if (rest > 0) {
// Upload-Bereich für die 2. Analyse wieder anbieten (mit E-Mail-Feld)
eingabe.style.display = 'block';
emailTeil.style.display = 'block';
document.getElementById('nochmalZeile').style.display = 'block';
}
document.getElementById('ergebnis').scrollIntoView({ behavior: 'smooth' });
}
zeigeStand();
})();
</script>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body>
</html>

View File

@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/en">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://behoerdenklar.pages.dev/en">
<meta property="og:title" content="Got a letter from a German authority?">
<meta property="og:description" content="Take a photo BehördenKlar explains official German letters in plain language, in 9 languages. Join the waiting list for 5 free analyses.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d; --papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d;
@@ -128,6 +142,15 @@
margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte); margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte);
font-size: 14.5px; color: var(--grau); font-size: 14.5px; color: var(--grau);
} }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
</head> </head>
<body> <body>
@@ -209,9 +232,13 @@
🎁 <strong>Your gift:</strong> analyse <strong>5 letters for free</strong> 🎁 <strong>Your gift:</strong> analyse <strong>5 letters for free</strong>
instead of 3. You get the code by email. instead of 3. You get the code by email.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste%20(English)&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist.%20%2F%20Please%20notify%20me%20when%20Beh%C3%B6rdenKlar%20is%20available."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 Sign up by email <input class="wl-input" type="email" name="EMAIL" placeholder="Your email address" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">Join the waiting list →</button>
</form>
<p class="klein"> <p class="klein">
We only store your email address for this one message. You can We only store your email address for this one message. You can
unsubscribe at any time. <a href="datenschutz.html">Privacy policy (in German)</a>. unsubscribe at any time. <a href="datenschutz.html">Privacy policy (in German)</a>.
@@ -226,6 +253,6 @@
</footer> </footer>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

1
webseite/favicon.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y="82" font-size="82">📬</text></svg>

After

Width:  |  Height:  |  Size: 108 B

View File

@@ -43,6 +43,6 @@
<a class="zurueck" href="index.html">← Zurück zur Startseite</a> <a class="zurueck" href="index.html">← Zurück zur Startseite</a>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

View File

@@ -3,8 +3,8 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BehördenKlar Brief rein. Klartext raus.</title> <title>Behördenbriefe einfach erklärt per Foto | BehördenKlar</title>
<meta name="description" content="BehördenKlar übersetzt Behördenbriefe in einfache Sprache. Foto machen, verstehen, richtig reagieren. Bald für iPhone Warteliste sichert 5 Gratis-Analysen."> <meta name="description" content="Brief vom Amt? Foto machen BehördenKlar erklärt ihn in einfacher Sprache, zeigt Fristen, übersetzt in 9 Sprachen. Warteliste: 5 Gratis-Analysen.">
<link rel="alternate" hreflang="de" href="https://behoerdenklar.pages.dev/"> <link rel="alternate" hreflang="de" href="https://behoerdenklar.pages.dev/">
<link rel="alternate" hreflang="tr" href="https://behoerdenklar.pages.dev/tr"> <link rel="alternate" hreflang="tr" href="https://behoerdenklar.pages.dev/tr">
<link rel="alternate" hreflang="ar" href="https://behoerdenklar.pages.dev/ar"> <link rel="alternate" hreflang="ar" href="https://behoerdenklar.pages.dev/ar">
@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.pages.dev/">
<meta property="og:title" content="Brief vom Amt? Endlich verstanden.">
<meta property="og:description" content="Foto machen BehördenKlar erklärt Behördenbriefe in einfacher Sprache und 9 Sprachen. Warteliste sichert 5 Gratis-Analysen.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier: #faf7f0;
@@ -85,6 +99,18 @@
transition: transform 0.12s ease, box-shadow 0.12s ease; transition: transform 0.12s ease, box-shadow 0.12s ease;
} }
.cta:hover { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--tinte); } .cta:hover { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--tinte); }
/* Sekundär-Knopf: gleiche Form, heller — für die zweite, gleichwertige Wahl */
.cta-sek { background: #fff; color: var(--amtsblau); }
.hero-unter { margin-top: 18px; font-size: 16px; color: var(--grau); line-height: 1.7; }
.hero-unter a { color: var(--amtsblau); font-weight: 700; }
.hero-unter strong { color: var(--tinte); }
.probier-box {
margin-top: 26px; text-align: center;
background: var(--papier-dunkel); border: 2px dashed var(--tinte);
padding: 24px 22px;
}
.probier-box p { font-size: 18px; margin-bottom: 16px; }
.probier-box .cta { width: auto; }
.stempel { .stempel {
display: inline-block; padding: 7px 14px; display: inline-block; padding: 7px 14px;
border: 2.5px solid var(--stempelrot); color: var(--stempelrot); border: 2.5px solid var(--stempelrot); color: var(--stempelrot);
@@ -229,7 +255,54 @@
} }
footer { margin-top: 20px; font-size: 14.5px; color: var(--grau); } footer { margin-top: 20px; font-size: 14.5px; color: var(--grau); }
footer a { color: var(--grau); } footer a { color: var(--grau); }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Was kostet die App?",
"acceptedAnswer": { "@type": "Answer", "text": "Die App ist gratis. Die ersten 3 Briefe sind auch gratis (mit Code: 5). Danach gibt es ein günstiges Abo. Sie testen zuerst — dann entscheiden Sie." }
},
{
"@type": "Question",
"name": "Welche Briefe kann die App erklären?",
"acceptedAnswer": { "@type": "Answer", "text": "Briefe vom Jobcenter, von der Ausländerbehörde, Rentenversicherung, Krankenkasse, Familienkasse (Kindergeld), vom Finanzamt oder der Bußgeldstelle — kurz: fast jeden offiziellen Brief und Bescheid." }
},
{
"@type": "Question",
"name": "In welche Sprachen übersetzt die App?",
"acceptedAnswer": { "@type": "Answer", "text": "Arabisch, Türkisch, Englisch, Ukrainisch, Russisch, Polnisch, Farsi, Rumänisch und Französisch. Die deutschen Amts-Wörter bleiben sichtbar, damit Sie sie im Brief wiederfinden." }
},
{
"@type": "Question",
"name": "Was passiert mit meinen Briefen?",
"acceptedAnswer": { "@type": "Answer", "text": "Ihre Briefe bleiben auf Ihrem Handy — sicher verschlüsselt. Für die Analyse wird das Foto einmal sicher an die KI geschickt. Nach spätestens 30 Tagen wird es dort gelöscht. Sie brauchen kein Konto." }
},
{
"@type": "Question",
"name": "Ersetzt die App einen Anwalt?",
"acceptedAnswer": { "@type": "Answer", "text": "Nein. Die App erklärt Briefe — sie ist keine Rechtsberatung. Bei wichtigen Entscheidungen (z. B. Widerspruch) hilft eine Beratungsstelle oder ein Anwalt." }
},
{
"@type": "Question",
"name": "Kommt die App auch für Android?",
"acceptedAnswer": { "@type": "Answer", "text": "Ja, Android ist geplant. Das iPhone kommt zuerst. Auf der Warteliste erfahren Sie es als Erste." }
}
]
}
</script>
</head> </head>
<body> <body>
<div class="wrap"> <div class="wrap">
@@ -258,9 +331,14 @@
Brief in einfachen Worten. <em>Brief rein. Klartext raus.</em> Brief in einfachen Worten. <em>Brief rein. Klartext raus.</em>
</p> </p>
<div class="hero-fuss"> <div class="hero-fuss">
<a class="cta" href="#anmelden">Jetzt anmelden&nbsp;</a> <a class="cta" href="demo.html">📷 Brief testen — 2× gratis</a>
<span class="stempel">Bald im App&nbsp;Store</span> <a class="cta cta-sek" href="#anmelden">✉️ Auf die Warteliste</a>
</div> </div>
<p class="hero-unter">
<strong>Testen:</strong> mit Ihrem eigenen Brief, kein Konto, sofort im Browser.<br>
<strong>Warteliste:</strong> eine Nachricht zum Start — mit 5 Gratis-Analysen statt 3.
</p>
<p style="margin-top: 16px;"><span class="stempel">Bald im App&nbsp;Store</span></p>
</header> </header>
<section> <section>
@@ -289,6 +367,10 @@
Dazu bekommen Sie: eine Liste, was Sie tun müssen — und wenn Sie Dazu bekommen Sie: eine Liste, was Sie tun müssen — und wenn Sie
wollen, eine fertige Antwort. wollen, eine fertige Antwort.
</p> </p>
<div class="probier-box">
<p><strong>Genau das — mit Ihrem Brief.</strong> Kein Konto, sofort im Browser.</p>
<a class="cta" href="demo.html">📷 Jetzt 2× gratis testen&nbsp;</a>
</div>
</section> </section>
<section> <section>
@@ -348,12 +430,15 @@
</p> </p>
<p class="bonus-zeile"> <p class="bonus-zeile">
🎁 <strong>Ihr Dankeschön:</strong> Sie können <strong>5 Briefe 🎁 <strong>Ihr Dankeschön:</strong> Sie können <strong>5 Briefe
gratis</strong> erklären lassen — statt 3. Den Code bekommen Sie gratis</strong> erklären lassen — statt 3. Den Code bekommen Sie per E-Mail, sobald die App fertig ist.
per E-Mail.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 Per E-Mail eintragen <input class="wl-input" type="email" name="EMAIL" placeholder="Ihre E-Mail-Adresse" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">Auf die Warteliste eintragen →</button>
</form>
<p class="klein"> <p class="klein">
Wir speichern Ihre E-Mail-Adresse nur für diese eine Nachricht. Wir speichern Ihre E-Mail-Adresse nur für diese eine Nachricht.
Sie können sich jederzeit abmelden — <a href="datenschutz.html">Datenschutzerklärung</a>. Sie können sich jederzeit abmelden — <a href="datenschutz.html">Datenschutzerklärung</a>.
@@ -367,6 +452,14 @@
<summary>Was kostet die App?</summary> <summary>Was kostet die App?</summary>
<p>Die App ist gratis. Die ersten 3 Briefe sind auch gratis (mit Code: 5). Danach gibt es ein günstiges Abo. Sie testen zuerst — dann entscheiden Sie.</p> <p>Die App ist gratis. Die ersten 3 Briefe sind auch gratis (mit Code: 5). Danach gibt es ein günstiges Abo. Sie testen zuerst — dann entscheiden Sie.</p>
</details> </details>
<details>
<summary>Welche Briefe kann die App erklären?</summary>
<p>Briefe vom Jobcenter, von der Ausländerbehörde, Rentenversicherung, Krankenkasse, Familienkasse (Kindergeld), vom Finanzamt oder der Bußgeldstelle — kurz: fast jeden offiziellen Brief und Bescheid.</p>
</details>
<details>
<summary>In welche Sprachen übersetzt die App?</summary>
<p>Arabisch, Türkisch, Englisch, Ukrainisch, Russisch, Polnisch, Farsi, Rumänisch und Französisch. Die deutschen Amts-Wörter bleiben sichtbar, damit Sie sie im Brief wiederfinden.</p>
</details>
<details> <details>
<summary>Was passiert mit meinen Briefen?</summary> <summary>Was passiert mit meinen Briefen?</summary>
<p>Ihre Briefe bleiben auf Ihrem Handy — sicher verschlüsselt. Für die Analyse wird das Foto einmal sicher an die KI geschickt. Nach spätestens 30 Tagen wird es dort gelöscht. Sie brauchen kein Konto. Mehr dazu in der <a href="datenschutz.html">Datenschutzerklärung</a>.</p> <p>Ihre Briefe bleiben auf Ihrem Handy — sicher verschlüsselt. Für die Analyse wird das Foto einmal sicher an die KI geschickt. Nach spätestens 30 Tagen wird es dort gelöscht. Sie brauchen kein Konto. Mehr dazu in der <a href="datenschutz.html">Datenschutzerklärung</a>.</p>
@@ -398,6 +491,6 @@
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

View File

@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/pl">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="pl_PL">
<meta property="og:url" content="https://behoerdenklar.pages.dev/pl">
<meta property="og:title" content="List z niemieckiego urzędu?">
<meta property="og:description" content="Zrób zdjęcie BehördenKlar wyjaśni list prostym językiem, po polsku. Zapisz się na listę: 5 bezpłatnych analiz.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d; --papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d;
@@ -128,6 +142,15 @@
margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte); margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte);
font-size: 14.5px; color: var(--grau); font-size: 14.5px; color: var(--grau);
} }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
</head> </head>
<body> <body>
@@ -211,9 +234,13 @@
🎁 <strong>Twój prezent:</strong> analizuj <strong>5 listów za 🎁 <strong>Twój prezent:</strong> analizuj <strong>5 listów za
darmo</strong> zamiast 3. Kod dostaniesz e-mailem. darmo</strong> zamiast 3. Kod dostaniesz e-mailem.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste%20(Polnisch)&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist.%20%2F%20Please%20notify%20me%20when%20Beh%C3%B6rdenKlar%20is%20available."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 Zapisz się e-mailem <input class="wl-input" type="email" name="EMAIL" placeholder="Twój adres e-mail" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">Zapisz się na listę →</button>
</form>
<p class="klein"> <p class="klein">
Zapisujemy Twój adres tylko dla tej jednej wiadomości. Możesz Zapisujemy Twój adres tylko dla tej jednej wiadomości. Możesz
wypisać się w każdej chwili. <a href="datenschutz.html">Polityka prywatności (po niemiecku)</a>. wypisać się w każdej chwili. <a href="datenschutz.html">Polityka prywatności (po niemiecku)</a>.
@@ -228,6 +255,6 @@
</footer> </footer>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

4
webseite/robots.txt Normal file
View File

@@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: https://behoerdenklar.pages.dev/sitemap.xml

View File

@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/ru">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="ru_RU">
<meta property="og:url" content="https://behoerdenklar.pages.dev/ru">
<meta property="og:title" content="Письмо из немецкого ведомства?">
<meta property="og:description" content="Сфотографируйте письмо — BehördenKlar объяснит его простым языком, по-русски. Запишитесь в список: 5 бесплатных анализов.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d; --papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d;
@@ -128,6 +142,15 @@
margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte); margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte);
font-size: 14.5px; color: var(--grau); font-size: 14.5px; color: var(--grau);
} }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
</head> </head>
<body> <body>
@@ -210,9 +233,13 @@
🎁 <strong>Ваш подарок:</strong> анализируйте <strong>5 писем 🎁 <strong>Ваш подарок:</strong> анализируйте <strong>5 писем
бесплатно</strong> вместо 3. Код придёт по электронной почте. бесплатно</strong> вместо 3. Код придёт по электронной почте.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste%20(Russisch)&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist.%20%2F%20Please%20notify%20me%20when%20Beh%C3%B6rdenKlar%20is%20available."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 Записаться по электронной почте <input class="wl-input" type="email" name="EMAIL" placeholder="Ваш адрес эл. почты" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">Записаться в список →</button>
</form>
<p class="klein"> <p class="klein">
Мы храним ваш адрес только для этого одного сообщения. Вы можете Мы храним ваш адрес только для этого одного сообщения. Вы можете
отписаться в любой момент. <a href="datenschutz.html">Политика конфиденциальности (на немецком)</a>. отписаться в любой момент. <a href="datenschutz.html">Политика конфиденциальности (на немецком)</a>.
@@ -227,6 +254,6 @@
</footer> </footer>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

11
webseite/sitemap.xml Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://behoerdenklar.pages.dev/</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/en</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/tr</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/ar</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/uk</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/ru</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/pl</loc><lastmod>2026-07-23</lastmod></url>
<url><loc>https://behoerdenklar.pages.dev/demo</loc><lastmod>2026-07-24</lastmod></url>
</urlset>

View File

@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/tr">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="tr_TR">
<meta property="og:url" content="https://behoerdenklar.pages.dev/tr">
<meta property="og:title" content="Alman resmî mektubu mu geldi?">
<meta property="og:description" content="Fotoğraf çekin BehördenKlar resmî mektupları basit bir dille, Türkçe açıklar. Bekleme listesine katılın: 5 ücretsiz analiz.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d; --papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d;
@@ -128,6 +142,15 @@
margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte); margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte);
font-size: 14.5px; color: var(--grau); font-size: 14.5px; color: var(--grau);
} }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
</head> </head>
<body> <body>
@@ -210,9 +233,13 @@
🎁 <strong>Hediyeniz:</strong> 3 yerine <strong>5 mektubu ücretsiz</strong> 🎁 <strong>Hediyeniz:</strong> 3 yerine <strong>5 mektubu ücretsiz</strong>
analiz edin. Kodu e-posta ile alırsınız. analiz edin. Kodu e-posta ile alırsınız.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste%20(Tuerkisch)&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist.%20%2F%20Please%20notify%20me%20when%20Beh%C3%B6rdenKlar%20is%20available."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 E-posta ile kaydol <input class="wl-input" type="email" name="EMAIL" placeholder="E-posta adresiniz" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">Bekleme listesine katıl →</button>
</form>
<p class="klein"> <p class="klein">
E-posta adresinizi sadece bu bir mesaj için saklarız. İstediğiniz E-posta adresinizi sadece bu bir mesaj için saklarız. İstediğiniz
zaman listeden çıkabilirsiniz. <a href="datenschutz.html">Gizlilik politikası (Almanca)</a>. zaman listeden çıkabilirsiniz. <a href="datenschutz.html">Gizlilik politikası (Almanca)</a>.
@@ -227,6 +254,6 @@
</footer> </footer>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

View File

@@ -12,6 +12,20 @@
<link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk"> <link rel="alternate" hreflang="uk" href="https://behoerdenklar.pages.dev/uk">
<link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru"> <link rel="alternate" hreflang="ru" href="https://behoerdenklar.pages.dev/ru">
<link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl"> <link rel="alternate" hreflang="pl" href="https://behoerdenklar.pages.dev/pl">
<link rel="alternate" hreflang="x-default" href="https://behoerdenklar.pages.dev/">
<link rel="canonical" href="https://behoerdenklar.pages.dev/uk">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="uk_UA">
<meta property="og:url" content="https://behoerdenklar.pages.dev/uk">
<meta property="og:title" content="Лист від німецької установи?">
<meta property="og:description" content="Сфотографуйте лист — BehördenKlar пояснить його простою мовою, українською. Запишіться в список: 5 безкоштовних аналізів.">
<meta property="og:image" content="https://behoerdenklar.pages.dev/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="BehördenKlar Brief vom Amt. Endlich verstanden.">
<meta name="twitter:card" content="summary_large_image">
<style> <style>
:root { :root {
--papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d; --papier: #faf7f0; --papier-dunkel: #f1ecdf; --tinte: #21211d;
@@ -128,6 +142,15 @@
margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte); margin-top: 56px; padding-top: 14px; border-top: 2px solid var(--tinte);
font-size: 14.5px; color: var(--grau); font-size: 14.5px; color: var(--grau);
} }
/* Warteliste-Formular (Brevo) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
}
.wl-input::placeholder { color: #9a958a; }
.wl-btn { width: 100%; cursor: pointer; text-align: center; font-family: inherit; }
</style> </style>
</head> </head>
<body> <body>
@@ -211,9 +234,13 @@
🎁 <strong>Ваш подарунок:</strong> аналізуйте <strong>5 листів 🎁 <strong>Ваш подарунок:</strong> аналізуйте <strong>5 листів
безкоштовно</strong> замість 3. Код отримаєте електронною поштою. безкоштовно</strong> замість 3. Код отримаєте електронною поштою.
</p> </p>
<a class="cta" href="mailto:behoerdenbriefhelfer@gmail.com?subject=Anmeldung%20Warteliste%20(Ukrainisch)&body=Hallo%2C%20bitte%20informiert%20mich%2C%20wenn%20Beh%C3%B6rdenKlar%20verf%C3%BCgbar%20ist.%20%2F%20Please%20notify%20me%20when%20Beh%C3%B6rdenKlar%20is%20available."> <form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
📧 Записатися електронною поштою <input class="wl-input" type="email" name="EMAIL" placeholder="Ваша електронна пошта" required autocomplete="email">
</a> <input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta wl-btn" type="submit">Записатися в список →</button>
</form>
<p class="klein"> <p class="klein">
Ми зберігаємо вашу адресу лише для цього одного повідомлення. Ви Ми зберігаємо вашу адресу лише для цього одного повідомлення. Ви
можете відписатися будь-коли. <a href="datenschutz.html">Політика конфіденційності (німецькою)</a>. можете відписатися будь-коли. <a href="datenschutz.html">Політика конфіденційності (німецькою)</a>.
@@ -228,6 +255,6 @@
</footer> </footer>
</div> </div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile --> <!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "218273478b5845c6bc821588d7d823db"}'></script> <script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body> </body>
</html> </html>

BIN
webseite/vorschau.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB