Compare commits

..

11 Commits

Author SHA1 Message Date
a5e1a7d70b Fehlermeldung: Auth-/Konfigfehler nicht dem Foto anlasten
401/403 vom KI-Dienst sagte bisher 'machen Sie ein besseres Foto'. Jetzt
eigener Zweig (ki_konfig) mit ehrlicher Meldung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 23:47:47 +02:00
e8a48049dd Stripe: auf LIVE-Preise umgestellt (Worker + Startseite + Demo)
price_1U6BNn… = 5 Analysen / 2,99 EUR
price_1U6BPR… = 15 Analysen / 6,99 EUR

Achtung: funktioniert erst, wenn STRIPE_SECRET_KEY auf sk_live_ steht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 17:41:45 +02:00
16e9d33b71 Branding: BehoerdenKlar by Webklar + Anbieter-Hinweis an der Kasse
Statt Statement-Descriptor-Trick: Webklar wird auf der Seite sichtbar
gemacht. Kauf-Boxen nennen Webklar GbR als Anbieter und sagen an, dass
auf der Kontoabrechnung 'Webklar' erscheint (verhindert Chargebacks).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 17:30:30 +02:00
874ba31344 SEO: 4 neue Ratgeber-Artikel (verstehen, uebersetzen, organisieren, antworten)
Gezielte Keyword-Seiten mit Title/H1/Meta/FAQ-Schema/Canonical, in
Ratgeber-Hub, Sitemap und (2 staerkste) auf der Startseite verlinkt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 00:12:19 +02:00
0b71cce57d Rechtstexte: AGB + Widerruf neu, Impressum/Datenschutz auf Webklar GbR
- Impressum: Webklar GbR (Justin Klein, Kenso Grimm), Kleinunternehmer §19,
  EU-Streitschlichtung; Steuernummer bewusst nicht veroeffentlicht
- Datenschutz: Verantwortlicher = Webklar GbR; neuer Abschnitt Bezahlung
  (Stripe) + Wiederherstellungs-Mail (Brevo)
- AGB (agb.html) + Widerrufsbelehrung (widerruf.html) neu, verlinkt
- Kauf-UI: falsche 'inkl. USt' entfernt -> §19-Hinweis; AGB/Widerruf im
  Pflicht-Haekchen und in den Footern verlinkt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 00:03:25 +02:00
1f3aad7e62 Startseite: Guthaben-Kauf direkt oben (Preise + Stripe-Checkout)
Neue Kauf-Sektion #kaufen gleich unter dem Hero (Pakete 5/15 Analysen,
Pflicht-Einwilligung, POST /kaufen -> Stripe). Hero-CTA 'Guthaben kaufen'.
Rueckkehr/Aktivierung laeuft wie gehabt ueber /demo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 19:56:26 +02:00
3c2e5c24ae Web-Kauf: Kauf-Block nach oben (jetzt §2, direkt hinter Upload)
Guthaben-Kauf erscheint jetzt gleich unter dem Upload statt ganz unten.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 19:52:49 +02:00
0634e3cd38 Web-Kauf: Guthaben jederzeit kaufbar (auch ohne Gratis-Test)
Kauf-Block ist von Anfang an sichtbar — beide Wege parallel: sofort kaufen
oder erst 2x gratis testen. Einleitungstext angepasst.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 19:46:51 +02:00
521f504aa3 Web-Kauf: Guthaben kaufen & nutzen im Browser (Stripe, Demo-Seite)
- demo.html: Kauf-Block mit Paketen (5/15 Analysen), Guthaben-Banner,
  Pflicht-Einwilligung (sofortige Leistung, Widerruf erlischt), Rückkehr
  von Stripe (/kauf-status), Wallet-Token in localStorage, bezahlte
  Analysen umgehen die Gratis-Sperre und zählen das Guthaben herunter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 19:40:58 +02:00
7440d35efb Web-Bezahlung Backend: Credit-Guthaben per Stripe (Phase 1)
- /kaufen: Stripe-Checkout-Session (REST, kein SDK)
- /kauf-status: nach Rueckkehr Zahlung pruefen -> Guthaben aktivieren ->
  signiertes Wallet-Token (HMAC) zurueckgeben
- /stripe-webhook: Signatur pruefen -> Guthaben aktivieren (idempotent) ->
  Wiederherstellungs-Link per Brevo mailen
- demoHandler: nimmt optional walletToken; gueltiges Guthaben umgeht die
  Gratis-Grenzen, wird nach Erfolg um 1 verringert
- neue Secrets: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET,
  TOKEN_SIGNING_SECRET, BREVO_API_KEY; PAKETE-Mapping (Price-ID->Credits,
  echte IDs noch einzutragen)

Typecheck gruen. Noch nicht deployed (wartet auf Stripe-Einrichtung).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 14:34:38 +02:00
ce8a08a14d Fix: neues Turnstile-Widget mit behoerdenklar.de als Hostname
Altes Widget war nur fuer pages.dev freigeschaltet -> auf der neuen Domain
kam kein Token, Demo blockiert. Neues Widget (Hostnames: behoerdenklar.de,
www, pages.dev): Sitekey in demo.html, Secret als Worker-Secret gesetzt.
Token-Erzeugung auf behoerdenklar.de verifiziert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 12:55:10 +02:00
13 changed files with 1704 additions and 90 deletions

View File

@@ -28,6 +28,14 @@ interface Env {
DEMO_TAGES_BUDGET: string;
/** Web-Demo: max. Analysen pro IP innerhalb von 30 Tagen */
DEMO_LIMIT_IP: string;
/** Bezahlung: `wrangler secret put STRIPE_SECRET_KEY` (Test: sk_test_…) */
STRIPE_SECRET_KEY: string;
/** Bezahlung: `wrangler secret put STRIPE_WEBHOOK_SECRET` (whsec_…) */
STRIPE_WEBHOOK_SECRET: string;
/** Bezahlung: `wrangler secret put TOKEN_SIGNING_SECRET` (langer Zufallswert) */
TOKEN_SIGNING_SECRET: string;
/** Bezahlung: `wrangler secret put BREVO_API_KEY` (für die Guthaben-Link-Mail) */
BREVO_API_KEY: string;
}
const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
@@ -167,7 +175,7 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
return demoFehler(403, 'origin', 'Aufruf nur von der BehördenKlar-Webseite erlaubt.', origin);
}
let body: { bild?: string; mimeType?: string; turnstileToken?: string; email?: string };
let body: { bild?: string; mimeType?: string; turnstileToken?: string; email?: string; walletToken?: string };
try {
body = await request.json();
} catch {
@@ -176,6 +184,7 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
const { bild, mimeType, turnstileToken } = body;
const email = typeof body.email === 'string' ? body.email.trim().toLowerCase() : null;
const walletToken = typeof body.walletToken === 'string' ? body.walletToken : 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);
@@ -199,8 +208,34 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
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)
const heute = new Date().toISOString().slice(0, 10);
// ── Bezahltes Guthaben? ──────────────────────────────────────────
// Ein gültiges Wallet-Token mit Guthaben umgeht die Gratis-Grenzen
// (die sind nur ein Kosten-Deckel für die kostenlose Stufe).
let walletId: string | null = null;
let walletRest = 0;
if (walletToken) {
walletId = await verifyWallet(walletToken, env.TOKEN_SIGNING_SECRET);
if (!walletId) {
return demoFehler(403, 'wallet_ungueltig', 'Ihr Zugangs-Token ist ungültig. Bitte laden Sie die Seite neu.', origin);
}
walletRest = parseInt((await env.RATE_LIMIT.get(`wallet:${walletId}`)) ?? '0', 10);
if (walletRest <= 0) {
return demoFehler(402, 'kein_guthaben', 'Ihr Guthaben ist aufgebraucht. Bitte kaufen Sie neues Guthaben.', origin);
}
}
const bezahlt = walletId !== null;
// Gratis-Stufe: Kontingent-Schlüssel (werden nur ohne Guthaben benutzt).
// IP-/Anon-Zähler sind TÄGLICH (Datum im Schlüssel), damit geteilte
// Anschlüsse (Familie, WLAN, Mobilfunk/CGNAT) nicht sofort blockieren.
let tagKey = '', ipKey = '', anonKey = '';
let mailKey: string | null = null;
let tagZahl = 0, ipZahl = 0, anonZahl = 0;
if (!bezahlt) {
// E-Mail prüfen (nur für die 2. Gratis-Analyse nötig)
if (email) {
if (!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email)) {
return demoFehler(400, 'email', 'Bitte geben Sie eine gültige E-Mail-Adresse ein.', origin);
@@ -212,20 +247,11 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
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}`;
tagKey = `demo:tag:${heute}`;
ipKey = `demo:ip:${ip}:${heute}`;
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([
@@ -234,25 +260,25 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
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);
tagZahl = parseInt(tagWert ?? '0', 10);
ipZahl = parseInt(ipWert ?? '0', 10);
anonZahl = parseInt(anonWert ?? '0', 10);
// Schicht 5: globales Tagesbudget (Kosten-Deckel)
// globales Tagesbudget (Kosten-Deckel der Gratis-Stufe)
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);
return demoFehler(429, 'budget', 'Die Gratis-Demo ist für heute ausgebucht. Kommen Sie morgen wieder — oder kaufen Sie Guthaben.', origin);
}
// Schicht 4: IP-Gesamtlimit pro Tag (Missbrauchs-Damm, großzügig)
// IP-Gesamtlimit pro Tag (Missbrauchs-Damm)
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);
return demoFehler(429, 'aufgebraucht', 'Für heute wurden über diesen Anschluss viele Gratis-Analysen genutzt. Kommen Sie morgen wieder — oder kaufen Sie Guthaben.', origin);
}
// Schicht 2/3: nach mehreren anonymen Analysen pro Anschluss E-Mail nötig;
// pro E-Mail dauerhaft nur 1x
// nach mehreren anonymen Analysen E-Mail nötig; pro E-Mail dauerhaft 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);
return demoFehler(429, 'aufgebraucht', 'Mit dieser E-Mail-Adresse wurde die Gratis-Analyse schon genutzt. Bitte kaufen Sie Guthaben, um weiterzumachen.', origin);
}
}
// KI-Analyse — identischer Aufbau wie in der App
@@ -292,6 +318,11 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
if (status === 429 || status >= 500) {
return demoFehler(503, 'ki', 'Der KI-Dienst ist gerade ausgelastet. Bitte versuchen Sie es in einer Minute erneut.', origin);
}
// 401/403 = Problem auf UNSERER Seite (z. B. ungültiger Schlüssel).
// Nutzer darf dann nicht aufgefordert werden, ein besseres Foto zu machen.
if (status === 401 || status === 403) {
return demoFehler(503, 'ki_konfig', 'Der Dienst ist gerade nicht erreichbar — das liegt an uns, nicht an Ihrem Foto. Bitte versuchen Sie es später noch einmal.', origin);
}
return demoFehler(502, 'ki', 'Die Analyse ist fehlgeschlagen. Bitte versuchen Sie es mit einem neuen, gut beleuchteten Foto.', origin);
}
@@ -303,6 +334,10 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
// 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;
if (bezahlt) {
// Bezahlte Analyse: Guthaben um 1 verringern (kein TTL — bleibt bestehen)
await env.RATE_LIMIT.put(`wallet:${walletId}`, String(walletRest - 1));
} else {
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 }),
@@ -315,6 +350,7 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
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);
@@ -332,17 +368,206 @@ async function demoHandler(request: Request, env: Env): Promise<Response> {
}
return Response.json(
{ analyse, versuch: email ? 2 : 1 },
{
analyse,
versuch: bezahlt ? 'bezahlt' : email ? 2 : 1,
guthaben: bezahlt ? walletRest - 1 : undefined,
},
{ headers: demoCorsHeaders(origin) }
);
}
// ============================================================
// Bezahlung (Stripe) — Credit-Guthaben, passwortlos ("Gutschein"-Prinzip)
// ============================================================
//
// Ablauf:
// 1. /kaufen -> legt eine Stripe-Checkout-Session an, gibt URL zurück
// 2. Stripe-Bezahlseite (Kartendaten fasst NUR Stripe an)
// 3a. /kauf-status -> nach Rückkehr: prüft Zahlung, aktiviert Guthaben,
// gibt ein signiertes Wallet-Token zurück (localStorage)
// 3b. /stripe-webhook -> Sicherungsnetz: aktiviert Guthaben + mailt den
// Wiederherstellungs-Link (Brevo)
// 4. /demo mit walletToken -> Analyse gegen Guthaben (siehe demoHandler)
/** Credit-Pakete: Stripe-Price-ID -> Anzahl Analysen.
* NACH dem Anlegen der Produkte in Stripe die echten `price_…`-IDs eintragen. */
const PAKETE: Record<string, { credits: number }> = {
// Stripe LIVE-Preise (Webklar). Echtes Geld — Änderungen nur mit Bedacht.
'price_1U6BNnBsRA1AOdnedGW5eefh': { credits: 5 }, // 2,99 € — 5 Analysen
'price_1U6BPRBsRA1AOdnemDUalzb8': { credits: 15 }, // 6,99 € — 15 Analysen
};
/** HMAC-SHA256 als Hex. */
async function hmacHex(secret: string, data: string): Promise<string> {
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(data));
return [...new Uint8Array(sig)].map((b) => b.toString(16).padStart(2, '0')).join('');
}
/** Konstantzeit-Vergleich zweier Hex-Strings. */
function gleich(a: string, b: string): boolean {
if (a.length !== b.length) return false;
let diff = 0;
for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
return diff === 0;
}
/** Wallet-Token = `<walletId>.<HMAC>`. */
async function signWallet(walletId: string, secret: string): Promise<string> {
return `${walletId}.${await hmacHex(secret, walletId)}`;
}
async function verifyWallet(token: string, secret: string): Promise<string | null> {
const i = token.lastIndexOf('.');
if (i < 0) return null;
const walletId = token.slice(0, i);
const sig = token.slice(i + 1);
return gleich(sig, await hmacHex(secret, walletId)) ? walletId : null;
}
/** Guthaben idempotent aktivieren (pro Stripe-Session nur einmal). */
async function aktiviereGuthaben(env: Env, sessionId: string, walletId: string, credits: number): Promise<void> {
const flagKey = `wallet_done:${sessionId}`;
if (await env.RATE_LIMIT.get(flagKey)) return; // schon aktiviert
await env.RATE_LIMIT.put(`wallet:${walletId}`, String(credits));
await env.RATE_LIMIT.put(flagKey, '1', { expirationTtl: 60 * 60 * 24 * 400 });
}
/** Guthaben-/Wiederherstellungs-Link per Brevo-Transaktionsmail. */
async function guthabenMail(env: Env, email: string, link: string, credits: number): Promise<void> {
await fetch('https://api.brevo.com/v3/smtp/email', {
method: 'POST',
headers: { 'api-key': env.BREVO_API_KEY, 'content-type': 'application/json', accept: 'application/json' },
body: JSON.stringify({
sender: { name: 'BehördenKlar', email: 'behoerdenbriefhelfer@gmail.com' },
to: [{ email }],
subject: 'Ihr BehördenKlar-Guthaben',
htmlContent:
`<p>Vielen Dank für Ihren Kauf!</p>` +
`<p>Ihr Guthaben: <strong>${credits} Analysen</strong>.</p>` +
`<p>Mit diesem Link nutzen Sie Ihr Guthaben auf jedem Gerät:</p>` +
`<p><a href="${link}">${link}</a></p>` +
`<p>Bitte bewahren Sie diese E-Mail auf — der Link ist Ihr Zugang.</p>`,
}),
});
}
/** POST /kaufen — Stripe-Checkout-Session anlegen. */
async function kaufenHandler(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: { priceId?: string };
try {
body = await request.json();
} catch {
return demoFehler(400, 'json', 'Ungültige Anfrage.', origin);
}
const priceId = typeof body.priceId === 'string' ? body.priceId : '';
const paket = PAKETE[priceId];
if (!paket) return demoFehler(400, 'paket', 'Unbekanntes Paket.', origin);
const walletId = crypto.randomUUID();
const params = new URLSearchParams();
params.set('mode', 'payment');
params.set('line_items[0][price]', priceId);
params.set('line_items[0][quantity]', '1');
params.set('success_url', `${origin}/demo?kauf=ok&session_id={CHECKOUT_SESSION_ID}`);
params.set('cancel_url', `${origin}/demo?kauf=abbruch`);
params.set('metadata[walletId]', walletId);
params.set('metadata[credits]', String(paket.credits));
params.set('metadata[origin]', origin);
const r = await fetch('https://api.stripe.com/v1/checkout/sessions', {
method: 'POST',
headers: { Authorization: `Bearer ${env.STRIPE_SECRET_KEY}`, 'content-type': 'application/x-www-form-urlencoded' },
body: params.toString(),
});
const s = (await r.json()) as { url?: string; error?: { message?: string; type?: string; code?: string } };
if (!r.ok || !s.url) {
console.log('Stripe-Checkout-Fehler', r.status, JSON.stringify(s).slice(0, 300));
// TEMP-DIAGNOSE (wieder entfernen): Stripe-Grund mitgeben
const grund = `${r.status} ${s.error?.type ?? ''} ${s.error?.code ?? ''} ${s.error?.message ?? ''}`.trim();
return demoFehler(502, 'stripe', `Die Bezahlseite konnte nicht geöffnet werden. [${grund}]`, origin);
}
return Response.json({ url: s.url }, { headers: demoCorsHeaders(origin) });
}
/** GET /kauf-status?session_id=… — nach Rückkehr: Zahlung prüfen, Guthaben aktivieren, Token liefern. */
async function kaufStatusHandler(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 (!origin || !DEMO_ORIGIN_MUSTER.test(origin)) return demoFehler(403, 'origin', 'Nicht erlaubt.', origin);
const sessionId = new URL(request.url).searchParams.get('session_id') ?? '';
if (!/^cs_[A-Za-z0-9_]+$/.test(sessionId)) return demoFehler(400, 'session', 'Ungültige Sitzung.', origin);
const r = await fetch(`https://api.stripe.com/v1/checkout/sessions/${sessionId}`, {
headers: { Authorization: `Bearer ${env.STRIPE_SECRET_KEY}` },
});
const s = (await r.json()) as { payment_status?: string; metadata?: Record<string, string> };
if (!r.ok || s.payment_status !== 'paid') {
return demoFehler(402, 'nicht_bezahlt', 'Die Zahlung ist noch nicht bestätigt. Bitte einen Moment warten und neu laden.', origin);
}
const walletId = s.metadata?.walletId;
const credits = parseInt(s.metadata?.credits ?? '0', 10);
if (!walletId || !credits) return demoFehler(500, 'meta', 'Kaufdaten unvollständig.', origin);
await aktiviereGuthaben(env, sessionId, walletId, credits);
const token = await signWallet(walletId, env.TOKEN_SIGNING_SECRET);
const rest = parseInt((await env.RATE_LIMIT.get(`wallet:${walletId}`)) ?? '0', 10);
return Response.json({ token, guthaben: rest }, { headers: demoCorsHeaders(origin) });
}
/** POST /stripe-webhook — Sicherungsnetz: Signatur prüfen, Guthaben aktivieren, Link mailen. */
async function webhookHandler(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') return new Response('nur POST', { status: 405 });
const sigHeader = request.headers.get('stripe-signature') ?? '';
const payload = await request.text();
const teile = Object.fromEntries(sigHeader.split(',').map((p) => p.split('=') as [string, string]));
const t = teile['t'];
const v1 = teile['v1'];
if (!t || !v1) return new Response('Signatur fehlt', { status: 400 });
const erwartet = await hmacHex(env.STRIPE_WEBHOOK_SECRET, `${t}.${payload}`);
if (!gleich(v1, erwartet)) return new Response('Signatur ungültig', { status: 400 });
const event = JSON.parse(payload) as {
type?: string;
data?: { object?: { id?: string; metadata?: Record<string, string>; customer_details?: { email?: string } } };
};
if (event.type === 'checkout.session.completed') {
const o = event.data?.object;
const walletId = o?.metadata?.walletId;
const credits = parseInt(o?.metadata?.credits ?? '0', 10);
if (o?.id && walletId && credits) {
await aktiviereGuthaben(env, o.id, walletId, credits);
const email = o.customer_details?.email;
const basis = o.metadata?.origin || 'https://behoerdenklar.de';
if (email) {
const token = await signWallet(walletId, env.TOKEN_SIGNING_SECRET);
await guthabenMail(env, email, `${basis}/demo?wallet=${encodeURIComponent(token)}`, credits).catch(() => {});
}
}
}
return new Response('ok', { status: 200 });
}
export default {
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);
}
const pfad = new URL(request.url).pathname;
// Web-Demo + Bezahl-Routen haben eigene Regeln
if (pfad === '/demo') return demoHandler(request, env);
if (pfad === '/kaufen') return kaufenHandler(request, env);
if (pfad === '/kauf-status') return kaufStatusHandler(request, env);
if (pfad === '/stripe-webhook') return webhookHandler(request, env);
if (request.method !== 'POST') {
return fehler(405, 'invalid_request_error', 'Nur POST erlaubt.');

184
webseite/agb.html Normal file
View File

@@ -0,0 +1,184 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AGB BehördenKlar</title>
<meta name="robots" content="noindex">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: #1a1a2e; background: #f4f8fb; line-height: 1.7;
}
.wrap { max-width: 640px; margin: 0 auto; padding: 32px 20px 64px; }
h1 { font-size: 28px; color: #144d8c; margin: 24px 0 4px; }
.stand { color: #4a5568; margin-bottom: 16px; }
h2 { font-size: 20px; color: #144d8c; margin: 24px 0 8px; }
p, li { margin-bottom: 8px; }
ul { padding-left: 24px; }
.karte {
background: #fff; border-radius: 16px; padding: 24px;
box-shadow: 0 2px 8px rgba(20, 77, 140, 0.08);
}
a { color: #1a6bc4; }
.zurueck { display: inline-block; margin-top: 24px; }
</style>
</head>
<body>
<div class="wrap">
<h1>Allgemeine Geschäftsbedingungen (AGB)</h1>
<p class="stand">für das Web-Angebot „BehördenKlar" — Stand: 18.08.2026</p>
<div class="karte">
<h2>§ 1 Anbieter und Geltungsbereich</h2>
<p>
Anbieter des Web-Angebots „BehördenKlar" (nachfolgend „wir") ist die
Webklar GbR, vertreten durch Justin Klein und Kenso Grimm, Am Schwimmbad
10, 67722 Winnweiler, E-Mail
<a href="mailto:behoerdenbriefhelfer@gmail.com">behoerdenbriefhelfer@gmail.com</a>.
</p>
<p>
Diese AGB gelten für den Kauf und die Nutzung von Guthaben für
Brief-Analysen, die Sie direkt in Ihrem Browser auf unserer Webseite
nutzen. Verbraucher ist jede natürliche Person, die das Angebot zu
Zwecken abschließt, die überwiegend weder ihrer gewerblichen noch ihrer
selbständigen beruflichen Tätigkeit zugerechnet werden können.
</p>
<h2>§ 2 Leistungsbeschreibung</h2>
<p>
BehördenKlar erklärt hochgeladene Behördenbriefe mit Hilfe einer
Künstlichen Intelligenz (KI) in einfacher Sprache, erkennt Fristen und
Termine und unterstützt beim Antworten. Mit einem Guthaben-Paket erwerben
Sie eine bestimmte Anzahl von Analysen (z. B. 5 oder 15). Je
durchgeführter Analyse wird Ihr Guthaben um eine Einheit verringert.
</p>
<p>
BehördenKlar erklärt Briefe verständlich, stellt aber
<strong>keine Rechtsberatung</strong> dar und liefert keine
rechtsverbindlichen Auskünfte. Da die Analyse durch eine KI erfolgt,
können Ergebnisse im Einzelfall unvollständig oder fehlerhaft sein;
prüfen Sie wichtige Angaben (insbesondere Fristen) stets selbst anhand
des Originalbriefs.
</p>
<h2>§ 3 Zustandekommen des Vertrags</h2>
<p>
Die Darstellung der Guthaben-Pakete auf der Webseite ist eine
Aufforderung zur Abgabe eines Angebots. Durch Auswahl eines Pakets und
Abschluss des Bezahlvorgangs über unseren Zahlungsdienstleister Stripe
geben Sie ein verbindliches Angebot ab. Der Vertrag kommt mit der
Bestätigung der erfolgreichen Zahlung und der Gutschrift des Guthabens
zustande.
</p>
<h2>§ 4 Preise und Zahlung</h2>
<p>
Es gelten die zum Zeitpunkt des Kaufs auf der Webseite angegebenen
Preise. <strong>Als Kleinunternehmer im Sinne von § 19 UStG weisen wir
keine Umsatzsteuer aus und berechnen keine.</strong>
</p>
<p>
Die Zahlung wird über Stripe abgewickelt (Stripe Payments Europe, Ltd.).
Die Zahlungsdaten geben Sie direkt bei Stripe ein; wir erhalten und
speichern keine vollständigen Zahlungsdaten. Der Kaufpreis ist sofort
mit Vertragsschluss fällig.
</p>
<h2>§ 5 Bereitstellung und Nutzung des Guthabens</h2>
<p>
Nach erfolgreicher Zahlung wird Ihr Guthaben unter einer zufälligen,
anonymen Kennung bereitgestellt. Ihr Browser erhält dafür einen
signierten Nachweis („Gutschein-Token"), der lokal gespeichert wird.
Ein Nutzerkonto oder Passwort ist nicht erforderlich.
</p>
<p>
Geben Sie beim Kauf eine E-Mail-Adresse an, senden wir Ihnen zusätzlich
einen Wiederherstellungs-Link, mit dem Sie Ihr Guthaben auf einem
anderen Gerät oder nach dem Löschen der Browserdaten weiter nutzen
können. <strong>Dieser Link wirkt wie ein Gutscheincode:</strong> Wer
über ihn verfügt, kann das Guthaben nutzen. Bewahren Sie ihn daher sicher
auf und geben Sie ihn nicht weiter.
</p>
<p>
Das Guthaben verfällt nicht durch bloßen Zeitablauf; es gelten die
gesetzlichen Verjährungsfristen. Eine Barauszahlung von Guthaben ist
ausgeschlossen.
</p>
<h2>§ 6 Widerrufsrecht</h2>
<p>
Verbrauchern steht ein gesetzliches Widerrufsrecht zu. Einzelheiten
ergeben sich aus unserer
<a href="widerruf.html">Widerrufsbelehrung</a>.
</p>
<p>
<strong>Wichtig:</strong> Da es sich um digitale Inhalte handelt, die
sofort bereitgestellt werden, erlischt Ihr Widerrufsrecht, wenn Sie vor
Ablauf der Widerrufsfrist ausdrücklich zugestimmt haben, dass wir mit der
Leistung beginnen, und Sie Ihre Kenntnis davon bestätigt haben, dass Sie
durch diese Zustimmung Ihr Widerrufsrecht verlieren (§ 356 Abs. 5 BGB).
Diese Bestätigung erfolgt über das Pflicht-Häkchen vor dem Kauf.
</p>
<h2>§ 7 Verfügbarkeit</h2>
<p>
Wir bemühen uns um eine hohe Verfügbarkeit des Dienstes, schulden diese
jedoch nicht ununterbrochen. Kurzzeitige Unterbrechungen, etwa wegen
Wartung oder Störungen bei eingesetzten Dienstleistern, können
vorkommen.
</p>
<h2>§ 8 Haftung</h2>
<p>
Wir haften unbeschränkt für Schäden aus der Verletzung des Lebens, des
Körpers oder der Gesundheit sowie für Vorsatz und grobe Fahrlässigkeit.
Bei einfacher Fahrlässigkeit haften wir nur bei Verletzung einer
wesentlichen Vertragspflicht (Kardinalpflicht) und der Höhe nach begrenzt
auf den vertragstypischen, vorhersehbaren Schaden. Im Übrigen ist die
Haftung ausgeschlossen.
</p>
<p>
Für die inhaltliche Richtigkeit der KI-gestützten Analysen übernehmen wir
keine Gewähr; maßgeblich ist stets der Originalbrief. Für rechtliche
Entscheidungen wenden Sie sich an eine Beratungsstelle oder eine
Rechtsanwältin/einen Rechtsanwalt.
</p>
<h2>§ 9 Datenschutz</h2>
<p>
Informationen zur Verarbeitung Ihrer Daten finden Sie in unserer
<a href="datenschutz.html">Datenschutzerklärung</a>.
</p>
<h2>§ 10 Streitbeilegung</h2>
<p>
Die EU-Kommission stellt eine Plattform zur Online-Streitbeilegung
bereit: <a href="https://ec.europa.eu/consumers/odr/" target="_blank" rel="noopener">https://ec.europa.eu/consumers/odr</a>.
Wir sind nicht verpflichtet und nicht bereit, an einem
Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle
teilzunehmen.
</p>
<h2>§ 11 Schlussbestimmungen</h2>
<p>
Es gilt das Recht der Bundesrepublik Deutschland unter Ausschluss des
UN-Kaufrechts. Zwingende Verbraucherschutzvorschriften des Staates, in
dem der Verbraucher seinen gewöhnlichen Aufenthalt hat, bleiben
unberührt. Sollte eine Bestimmung dieser AGB unwirksam sein, bleibt die
Wirksamkeit der übrigen Bestimmungen unberührt.
</p>
</div>
<p style="margin-top: 20px; font-size: 15px;">
<a href="widerruf.html">Widerrufsbelehrung</a> ·
<a href="datenschutz.html">Datenschutzerklärung</a> ·
<a href="impressum.html">Impressum</a>
</p>
<a class="zurueck" href="index.html">← Zurück zur Startseite</a>
</div>
<!-- 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

@@ -29,12 +29,13 @@
<body>
<div class="wrap">
<h1>Datenschutzerklärung</h1>
<p class="stand">für die App „BehördenKlar" — Stand: 14.07.2026</p>
<p class="stand">für die App und Webseite „BehördenKlar" — Stand: 18.08.2026</p>
<div class="karte">
<h2>1. Verantwortlicher</h2>
<p>
Justin Klein<br>
Webklar GbR<br>
vertreten durch Justin Klein und Kenso Grimm<br>
Am Schwimmbad 10<br>
67722 Winnweiler<br>
E-Mail: <a href="mailto:behoerdenbriefhelfer@gmail.com">behoerdenbriefhelfer@gmail.com</a>
@@ -176,7 +177,45 @@
</li>
</ul>
<h2>9. Reichweitenmessung (Webseite)</h2>
<h2>9. Bezahlung und Guthaben (Webseite)</h2>
<p>
Wenn Sie auf der Webseite Guthaben kaufen, um weitere Brief-Analysen im
Browser zu nutzen, verarbeiten wir die dafür nötigen Daten zur
Vertragserfüllung (Art. 6 Abs. 1 lit. b DSGVO):
</p>
<ul>
<li>
<strong>Zahlungsabwicklung durch Stripe.</strong> Die Bezahlung läuft
über Stripe Payments Europe, Ltd. (Irland) bzw. Stripe, Inc. (USA).
Ihre Zahlungsdaten (z. B. Kartennummer) geben Sie direkt bei Stripe
ein — <strong>wir sehen und speichern diese Daten nicht</strong>.
Stripe teilt uns nur mit, ob die Zahlung erfolgreich war, sowie eine
Zahlungs-Kennung. Es gelten zusätzlich die Datenschutzhinweise von
Stripe: <a href="https://stripe.com/de/privacy" target="_blank" rel="noopener">stripe.com/de/privacy</a>.
</li>
<li>
<strong>Guthaben-Verwaltung.</strong> Nach dem Kauf legen wir auf
unserem Server (Cloudflare) ein Guthaben unter einer zufälligen,
anonymen Kennung an und stellen Ihrem Browser dafür einen signierten
Nachweis („Gutschein-Token") aus. Damit können Sie Ihr Guthaben nutzen,
ohne ein Konto oder Passwort anzulegen. Die Kennung enthält keine
Angaben über Sie.
</li>
<li>
<strong>Wiederherstellungs-E-Mail (optional).</strong> Wenn Sie beim
Kauf eine E-Mail-Adresse angeben, senden wir Ihnen den
Wiederherstellungs-Link zu Ihrem Guthaben per E-Mail. Der Versand
erfolgt über Brevo (Sendinblue GmbH, Deutschland / Frankreich). Ihre
Adresse wird nur zu diesem Zweck verarbeitet.
</li>
</ul>
<p>
Angaben, die wir zur Erfüllung steuer- und handelsrechtlicher
Aufbewahrungspflichten benötigen (z. B. Zahlungsnachweise), bewahren wir
für die gesetzlichen Fristen auf (Art. 6 Abs. 1 lit. c DSGVO).
</p>
<h2>10. Reichweitenmessung (Webseite)</h2>
<p>
Auf dieser Webseite nutzen wir Cloudflare Web Analytics (Cloudflare,
Inc., USA) — eine datenschutzfreundliche Besucherstatistik
@@ -188,14 +227,14 @@
DSGVO).
</p>
<h2>10. Keine Rechtsberatung</h2>
<h2>11. Keine Rechtsberatung</h2>
<p>
BehördenKlar erklärt Briefe verständlich, ersetzt aber keine
Rechtsberatung. Bei rechtlich wichtigen Entscheidungen wenden Sie sich
an eine Beratungsstelle oder eine Anwältin/einen Anwalt.
</p>
<h2>11. Änderungen</h2>
<h2>12. Änderungen</h2>
<p>
Wir passen diese Datenschutzerklärung an, wenn sich die App oder die
Rechtslage ändert. Die aktuelle Fassung finden Sie immer auf dieser

View File

@@ -240,7 +240,7 @@
<div class="wrap">
<div class="briefkopf">
<span class="absender"><a href="index.html">📬 BehördenKlar</a></span>
<span class="absender"><a href="index.html">📬 BehördenKlar</a> <span style="font-weight:400;font-size:.62em;opacity:.6;letter-spacing:.04em;">by Webklar</span></span>
<span class="az mono">Formular D-01 · Gratis-Demo</span>
</div>
@@ -260,6 +260,12 @@
<p class="formular-kopf">Antrag auf Klartext · 2 Gratis-Analysen</p>
<div id="eingabe">
<p id="kaufOk" style="display: none; background: #e7f4ea; border: 1px solid #b7dfc1; color: #1a7f37; padding: 12px 14px; border-radius: 8px; margin-bottom: 14px; font-weight: 600;">
✅ Kauf erfolgreich! Ihr Guthaben wurde aktiviert.
</p>
<p id="guthabenBanner" class="bonus-zeile" style="display: none;">
💳 Ihr Guthaben: <strong id="guthabenZahl">0</strong> Analysen — laden Sie den nächsten Brief hoch.
</p>
<label class="konsens">
<input type="checkbox" id="konsens">
<span>
@@ -288,7 +294,7 @@
<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>
<div class="cf-turnstile" data-sitekey="0x4AAAAAAESi2p41B915R4hW" 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,
@@ -306,8 +312,46 @@
</div>
</section>
<section id="kaufBlock" style="display: none;">
<h2><span class="nr">§ 2</span> Guthaben kaufen &amp; sofort nutzen</h2>
<div class="antrag">
<p class="formular-kopf">Im Browser nutzen · ohne App Store</p>
<h3 style="font-size: 24px; line-height: 1.3;">Guthaben kaufen — sofort loslegen</h3>
<p style="margin-top: 10px;">
Sie müssen nicht erst testen: Kaufen Sie direkt Guthaben und nutzen Sie
BehördenKlar hier im Browser — auf jedem Gerät, ohne App. Ihr Guthaben
bleibt gespeichert und verfällt nicht.
</p>
<div id="paketListe" style="display: flex; flex-direction: column; gap: 12px; margin-top: 18px;"></div>
<label class="konsens" style="margin-top: 18px;">
<input type="checkbox" id="kaufKonsens">
<span>
Ich verlange ausdrücklich, dass die Analysen sofort nach dem Kauf zur
Verfügung stehen, und bestätige, dass mein Widerrufsrecht damit
erlischt. Ich habe die <a href="agb.html" target="_blank">AGB</a> und
die <a href="widerruf.html" target="_blank">Widerrufsbelehrung</a>
gelesen.
</span>
</label>
<div class="fehlerbox" id="kaufFehler" style="display: none; margin-top: 12px;"></div>
<p class="klein" style="margin-top: 12px;">
🔒 Sichere Bezahlung über Stripe — wir sehen Ihre Kartendaten nie.
Keine Umsatzsteuer (§ 19 UStG). Guthaben verfällt nicht.
</p>
<p class="klein" style="margin-top: 10px;">
Anbieter: <strong>Webklar GbR</strong> — BehördenKlar ist ein Angebot von
Webklar. Auf Ihrer Kontoabrechnung erscheint deshalb
<strong>„Webklar"</strong>.
</p>
</div>
</section>
<section id="ergebnis">
<h2><span class="nr">§ 2</span> Ihr Brief in Klartext</h2>
<h2><span class="nr">§ 3</span> Ihr Brief in Klartext</h2>
<div class="brief-karte">
<span class="karten-label neutral" id="ergBrieftyp">Brief</span>
@@ -337,7 +381,7 @@
</section>
<section id="werbung" style="display: none;">
<h2><span class="nr">§ 3</span> Wie geht es weiter?</h2>
<h2><span class="nr">§ 4</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>
@@ -371,6 +415,8 @@
<footer>
<a href="index.html">← Zur Startseite</a> ·
<a href="agb.html">AGB</a> ·
<a href="widerruf.html">Widerruf</a> ·
<a href="impressum.html">Impressum</a> ·
<a href="datenschutz.html">Datenschutzerklärung</a>
</footer>
@@ -381,9 +427,18 @@
<script>
(function () {
'use strict';
var ENDPUNKT = 'https://behoerdenklar-proxy.behoerdenbrief.workers.dev/demo';
var BASIS = 'https://behoerdenklar-proxy.behoerdenbrief.workers.dev';
var ENDPUNKT = BASIS + '/demo';
var KAUFEN_ENDPUNKT = BASIS + '/kaufen';
var STATUS_ENDPUNKT = BASIS + '/kauf-status';
var MAX_KANTE = 2000; // wie in der App: reicht für A4, spart Datenvolumen
// Guthaben-Pakete (Stripe TEST-Preise). Für Live später die Live-price_…-IDs.
var PAKETE = [
{ priceId: 'price_1U6BNnBsRA1AOdnedGW5eefh', titel: '5 Analysen', preis: '2,99 €' },
{ priceId: 'price_1U6BPRBsRA1AOdnemDUalzb8', titel: '15 Analysen', preis: '6,99 €', best: true },
];
var konsens = document.getElementById('konsens');
var startKnopf = document.getElementById('startKnopf');
var dateiFeld = document.getElementById('datei');
@@ -392,6 +447,23 @@
var status = document.getElementById('status');
var eingabe = document.getElementById('eingabe');
var fehlerBox = document.getElementById('fehler');
var kaufBlock = document.getElementById('kaufBlock');
var werbung = document.getElementById('werbung');
var guthabenBanner = document.getElementById('guthabenBanner');
var guthabenZahl = document.getElementById('guthabenZahl');
var kaufOk = document.getElementById('kaufOk');
var paketListe = document.getElementById('paketListe');
var kaufKonsens = document.getElementById('kaufKonsens');
var kaufFehler = document.getElementById('kaufFehler');
// Wallet (passwortloses Guthaben) — Token + zuletzt bekannter Stand lokal.
var WALLET_SCHLUESSEL = 'bk_wallet';
var GUTHABEN_SCHLUESSEL = 'bk_guthaben';
function walletToken() { return localStorage.getItem(WALLET_SCHLUESSEL) || ''; }
function setzeWallet(t) { localStorage.setItem(WALLET_SCHLUESSEL, t); }
function guthaben() { return parseInt(localStorage.getItem(GUTHABEN_SCHLUESSEL) || '0', 10); }
function setzeGuthaben(n) { localStorage.setItem(GUTHABEN_SCHLUESSEL, String(Math.max(0, n | 0))); }
function hatGuthaben() { return !!walletToken() && guthaben() > 0; }
// Schlüsselname bewusst 'v2': setzt evtl. falsch gezählte Stände (aus der
// Testphase) bei bestehenden Besuchern automatisch einmalig zurück.
@@ -400,12 +472,25 @@
function setzeBenutzt(n) { localStorage.setItem(SPEICHER_SCHLUESSEL, String(n)); }
function zeigeStand() {
// 2. Versuch: E-Mail-Feld einblenden; alles verbraucht: Eingabe sperren
// Bezahlter Modus: Eingabe offen, Guthaben-Stand zeigen, Gratis-Sperre egal
if (hatGuthaben()) {
eingabe.style.display = 'block';
guthabenBanner.style.display = 'block';
guthabenZahl.textContent = guthaben();
emailTeil.style.display = 'none';
fehlerBox.style.display = 'none';
kaufBlock.style.display = 'none';
return;
}
guthabenBanner.style.display = 'none';
// Kauf ist IMMER möglich — auch sofort, ohne die Gratis-Analysen zu nutzen.
kaufBlock.style.display = 'block';
// 2. Versuch: E-Mail-Feld einblenden; alles verbraucht: Gratis-Weg 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';
fehlerBox.innerHTML = 'Ihre 2 Gratis-Analysen sind verbraucht. Kaufen Sie unten <strong>Guthaben</strong>, um hier direkt weiterzumachen — oder tragen Sie sich für die App ein.';
werbung.style.display = 'block';
} else if (benutzt() === 1) {
emailTeil.style.display = 'block';
}
@@ -414,7 +499,7 @@
konsens.addEventListener('change', function () { startKnopf.disabled = !konsens.checked; });
startKnopf.addEventListener('click', function () {
fehlerBox.style.display = 'none';
if (benutzt() >= 1 && !emailFeld.value.trim()) {
if (!hatGuthaben() && 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.');
@@ -477,18 +562,21 @@
}
eingabe.style.display = 'none';
status.querySelector('.gross').textContent = 'Ihr Brief wird analysiert…';
status.style.display = 'block';
try {
var istPdf = datei.type === 'application/pdf';
var base64 = istPdf ? await pdfAlsBase64(datei) : await bildVerkleinern(datei);
var bezahlt = hatGuthaben();
var body = {
bild: base64,
mimeType: istPdf ? 'application/pdf' : 'image/jpeg',
turnstileToken: token,
};
var email = emailFeld.value.trim();
if (benutzt() >= 1 && email) body.email = email;
if (bezahlt) body.walletToken = walletToken();
else if (benutzt() >= 1 && email) body.email = email;
var antwort = await fetch(ENDPUNKT, {
method: 'POST',
@@ -514,14 +602,28 @@
zeigeStand();
return;
}
if (daten.code === 'kein_guthaben') {
setzeGuthaben(0);
guthabenBanner.style.display = 'none';
kaufBlock.style.display = 'block';
kaufBlock.scrollIntoView({ behavior: 'smooth' });
return;
}
zeigeFehler(daten.meldung || 'Etwas ist schiefgelaufen. Bitte erneut versuchen.');
return;
}
// Token erneuern — sonst würde die nächste Analyse ein "Seite neu laden" verlangen
if (window.turnstile) window.turnstile.reset();
if (daten.versuch === 'bezahlt' || typeof daten.guthaben === 'number') {
setzeGuthaben(daten.guthaben);
zeigeErgebnis(daten.analyse, null, daten.guthaben);
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';
@@ -548,7 +650,7 @@
return { farbe: farbe, text: punkt + ' ' + text };
}
function zeigeErgebnis(analyse, versuch) {
function zeigeErgebnis(analyse, versuch, guthabenRest) {
status.style.display = 'none';
document.getElementById('ergBrieftyp').textContent = analyse.brieftyp || 'Ihr Brief';
document.getElementById('ergKern').textContent = analyse.kernaussage || '';
@@ -586,6 +688,26 @@
}
document.getElementById('ergebnis').style.display = 'block';
// Bezahlter Modus: Guthaben-Stand zeigen, Eingabe für den nächsten Brief öffnen
if (typeof guthabenRest === 'number') {
werbung.style.display = 'none';
kaufOk.style.display = 'none';
if (guthabenRest > 0) {
eingabe.style.display = 'block';
guthabenBanner.style.display = 'block';
guthabenZahl.textContent = guthabenRest;
emailTeil.style.display = 'none';
kaufBlock.style.display = 'none';
} else {
eingabe.style.display = 'none';
guthabenBanner.style.display = 'none';
kaufBlock.style.display = 'block';
}
document.getElementById('ergebnis').scrollIntoView({ behavior: 'smooth' });
return;
}
var rest = 2 - benutzt();
document.getElementById('restZeile').textContent =
rest > 0 ? 'Noch ' + rest + ' Gratis-Analyse übrig' : 'Ihre 2 Gratis-Analysen sind verbraucht';
@@ -601,6 +723,115 @@
document.getElementById('ergebnis').scrollIntoView({ behavior: 'smooth' });
}
// ---- Guthaben kaufen ------------------------------------------------
function rendrePakete() {
paketListe.innerHTML = '';
PAKETE.forEach(function (p) {
var b = document.createElement('button');
b.className = 'cta';
b.type = 'button';
b.style.width = '100%';
b.style.display = 'flex';
b.style.justifyContent = 'space-between';
b.style.alignItems = 'center';
var links = document.createElement('span');
links.textContent = (p.best ? '⭐ ' : '') + p.titel;
var rechts = document.createElement('strong');
rechts.textContent = p.preis;
b.appendChild(links);
b.appendChild(rechts);
b.addEventListener('click', function () { starteKauf(p.priceId, b); });
paketListe.appendChild(b);
});
}
function starteKauf(priceId, knopf) {
if (!kaufKonsens.checked) {
kaufFehler.style.display = 'block';
kaufFehler.textContent = 'Bitte bestätigen Sie zuerst das Häkchen, um fortzufahren.';
kaufKonsens.focus();
return;
}
kaufFehler.style.display = 'none';
var alt = knopf.innerHTML;
knopf.disabled = true;
knopf.textContent = 'Weiter zu Stripe …';
fetch(KAUFEN_ENDPUNKT, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ priceId: priceId }),
})
.then(function (r) { return r.json(); })
.then(function (d) {
if (d && d.url) { window.location.href = d.url; return; }
throw new Error('keine url');
})
.catch(function () {
knopf.disabled = false;
knopf.innerHTML = alt;
kaufFehler.style.display = 'block';
kaufFehler.textContent = 'Die Bezahlseite konnte nicht geöffnet werden. Bitte erneut versuchen.';
});
}
// ---- Rückkehr von Stripe / Wallet-Wiederherstellung -----------------
function reinigeUrl() {
if (window.history.replaceState) {
window.history.replaceState({}, document.title, window.location.pathname);
}
}
function holeKaufStatus(sid, n) {
fetch(STATUS_ENDPUNKT + '?session_id=' + encodeURIComponent(sid))
.then(function (r) { return r.json().then(function (d) { return { ok: r.ok, d: d }; }); })
.then(function (res) {
if (res.ok && res.d && res.d.token) {
setzeWallet(res.d.token);
setzeGuthaben(res.d.guthaben);
status.style.display = 'none';
kaufOk.style.display = 'block';
zeigeStand();
document.getElementById('demo').scrollIntoView({ behavior: 'smooth' });
return;
}
if (n < 4) { setTimeout(function () { holeKaufStatus(sid, n + 1); }, 1500); return; }
status.style.display = 'none';
zeigeFehler('Ihre Zahlung wird noch bestätigt. Bitte laden Sie die Seite in einer Minute neu.');
})
.catch(function () {
status.style.display = 'none';
zeigeFehler('Die Zahlungsbestätigung konnte nicht geladen werden. Bitte Seite neu laden.');
});
}
function pruefeRueckkehr() {
var p = new URLSearchParams(window.location.search);
var w = p.get('wallet');
if (w) { setzeWallet(w); setzeGuthaben(Math.max(guthaben(), 1)); reinigeUrl(); return; }
var kauf = p.get('kauf');
if (kauf === 'abbruch') {
reinigeUrl();
fehlerBox.style.display = 'block';
fehlerBox.textContent = 'Kauf abgebrochen — es wurde nichts berechnet.';
return;
}
if (kauf === 'ok') {
var sid = p.get('session_id');
reinigeUrl();
if (!sid) return;
status.querySelector('.gross').textContent = 'Ihr Kauf wird bestätigt …';
eingabe.style.display = 'none';
status.style.display = 'block';
holeKaufStatus(sid, 0);
}
}
kaufKonsens.addEventListener('change', function () {
if (kaufKonsens.checked) kaufFehler.style.display = 'none';
});
rendrePakete();
pruefeRueckkehr();
zeigeStand();
})();
</script>

View File

@@ -27,19 +27,41 @@
<div class="karte">
<p><strong>Angaben gemäß § 5 DDG:</strong></p>
<p style="margin-top: 12px;">
Justin Klein<br>
Webklar GbR<br>
Am Schwimmbad 10<br>
67722 Winnweiler<br>
Deutschland
</p>
<p style="margin-top: 12px;">
<strong>Vertretungsberechtigte Gesellschafter:</strong><br>
Justin Klein, Kenso Grimm
</p>
<p style="margin-top: 12px;">
E-Mail: <a href="mailto:behoerdenbriefhelfer@gmail.com">behoerdenbriefhelfer@gmail.com</a>
</p>
<p style="margin-top: 16px;">
<strong>Verantwortlich für den Inhalt:</strong><br>
<strong>Umsatzsteuer:</strong><br>
Als Kleinunternehmer im Sinne von § 19 UStG wird keine Umsatzsteuer
berechnet und ausgewiesen.
</p>
<p style="margin-top: 16px;">
<strong>Verantwortlich für den Inhalt nach § 18 Abs. 2 MStV:</strong><br>
Justin Klein (Anschrift wie oben)
</p>
<p style="margin-top: 16px;">
<strong>Verbraucherstreitbeilegung:</strong><br>
Plattform der EU-Kommission zur Online-Streitbeilegung:
<a href="https://ec.europa.eu/consumers/odr/" target="_blank" rel="noopener">https://ec.europa.eu/consumers/odr</a>.
Wir sind nicht verpflichtet und nicht bereit, an einem
Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle
teilzunehmen.
</p>
</div>
<p style="margin-top: 20px; font-size: 15px;">
<a href="agb.html">AGB</a> ·
<a href="widerruf.html">Widerrufsbelehrung</a> ·
<a href="datenschutz.html">Datenschutzerklärung</a>
</p>
<a class="zurueck" href="index.html">← Zurück zur Startseite</a>
</div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->

View File

@@ -358,7 +358,7 @@
<div class="wrap">
<div class="briefkopf">
<span class="absender">📬 BehördenKlar</span>
<span class="absender">📬 BehördenKlar <span style="font-weight:400;font-size:.62em;opacity:.6;letter-spacing:.04em;">by Webklar</span></span>
<span class="az mono">Az: KLAR-01/2026 &nbsp;·&nbsp; Anlage: 1 App</span>
</div>
<nav class="sprachen" aria-label="Sprache wählen">
@@ -382,7 +382,8 @@
</p>
<div class="hero-fuss">
<a class="cta" href="demo.html">📷 Brief testen — 2× gratis</a>
<a class="cta cta-sek" href="#anmelden">✉️ Auf die Warteliste</a>
<a class="cta cta-sek" href="#kaufen">💳 Guthaben kaufen</a>
<a class="cta cta-sek" href="#anmelden">✉️ Warteliste</a>
</div>
<p class="hero-unter">
<strong>Testen:</strong> mit Ihrem eigenen Brief, kein Konto, sofort im Browser.<br>
@@ -391,6 +392,43 @@
<p style="margin-top: 16px;"><span class="stempel">Bald im App&nbsp;Store</span></p>
</header>
<section id="kaufen">
<div class="antrag" style="border: 2px solid var(--amtsblau, #1d4e89);">
<p class="formular-kopf">Sofort nutzen · ohne App Store · ohne Konto</p>
<h3 style="font-size: 26px; line-height: 1.25; margin-bottom: 6px;">Guthaben kaufen und direkt loslegen</h3>
<p style="margin-top: 10px;">
Sie müssen nicht warten: Kaufen Sie Guthaben und lassen Sie Ihre Briefe
sofort hier im Browser erklären — auf jedem Gerät. Ihr Guthaben bleibt
gespeichert und verfällt nicht.
</p>
<div id="hpPaketListe" style="display: flex; flex-direction: column; gap: 12px; margin-top: 18px;"></div>
<label style="display: flex; gap: 10px; align-items: flex-start; margin-top: 18px; font-size: 14px; line-height: 1.5; cursor: pointer;">
<input type="checkbox" id="hpKaufKonsens" style="margin-top: 3px; flex-shrink: 0;">
<span>
Ich verlange ausdrücklich, dass die Analysen sofort nach dem Kauf zur
Verfügung stehen, und bestätige, dass mein Widerrufsrecht damit
erlischt. Ich habe die <a href="agb.html" target="_blank">AGB</a> und
die <a href="widerruf.html" target="_blank">Widerrufsbelehrung</a>
gelesen.
</span>
</label>
<p id="hpKaufFehler" style="display: none; margin-top: 12px; color: #b3261e; font-size: 14px; font-weight: 600;"></p>
<p class="klein" style="margin-top: 12px;">
🔒 Sichere Bezahlung über Stripe — wir sehen Ihre Kartendaten nie.
Keine Umsatzsteuer (§ 19 UStG). · <a href="demo.html">Lieber erst 2× kostenlos testen →</a>
</p>
<p class="klein" style="margin-top: 10px;">
Anbieter: <strong>Webklar GbR</strong> — BehördenKlar ist ein Angebot von
Webklar. Auf Ihrer Kontoabrechnung erscheint deshalb
<strong>„Webklar"</strong>.
</p>
</div>
</section>
<section>
<h2><span class="nr">§ 1</span> Vorher und Nachher</h2>
<div class="verwandlung">
@@ -547,6 +585,14 @@
<b>Widerspruch einlegen — so geht's</b>
<span>Welche Frist gilt und wie Sie einen Widerspruch schreiben — mit Muster-Text.</span>
</a>
<a class="rat-karte" href="/ratgeber/behoerdenbrief-verstehen">
<b>Behördenbrief verstehen</b>
<span>Amtsdeutsch in Klartext — Schritt für Schritt, mit den wichtigsten Amtswörtern.</span>
</a>
<a class="rat-karte" href="/ratgeber/behoerdenbrief-uebersetzen">
<b>Behördenbrief übersetzen</b>
<span>Amtspost in Ihrer Sprache erklärt — Arabisch, Türkisch, Ukrainisch und mehr.</span>
</a>
</div>
<p class="rat-alle"><a href="/ratgeber/">Alle Ratgeber ansehen →</a></p>
</section>
@@ -557,6 +603,8 @@
<div class="anlage">
Anlagen: <a href="/ratgeber/" style="color: inherit;">Ratgeber</a> ·
<a href="agb.html" style="color: inherit;">AGB</a> ·
<a href="widerruf.html" style="color: inherit;">Widerruf</a> ·
<a href="impressum.html" style="color: inherit;">Impressum</a> ·
<a href="datenschutz.html" style="color: inherit;">Datenschutzerklärung</a> ·
Kontakt: <a href="mailto:behoerdenbriefhelfer@gmail.com" style="color: inherit;">behoerdenbriefhelfer@gmail.com</a>
@@ -569,6 +617,64 @@
</div>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script>
// Guthaben-Kauf direkt von der Startseite (Rückkehr/Aktivierung läuft auf /demo).
(function () {
'use strict';
var BASIS = 'https://behoerdenklar-proxy.behoerdenbrief.workers.dev';
var PAKETE = [
{ priceId: 'price_1U6BNnBsRA1AOdnedGW5eefh', titel: '5 Analysen', preis: '2,99 €' },
{ priceId: 'price_1U6BPRBsRA1AOdnemDUalzb8', titel: '15 Analysen', preis: '6,99 €', best: true },
];
var liste = document.getElementById('hpPaketListe');
var konsens = document.getElementById('hpKaufKonsens');
var fehler = document.getElementById('hpKaufFehler');
if (!liste) return;
konsens.addEventListener('change', function () { if (konsens.checked) fehler.style.display = 'none'; });
PAKETE.forEach(function (p) {
var b = document.createElement('button');
b.className = 'cta';
b.type = 'button';
b.style.width = '100%';
b.style.display = 'flex';
b.style.justifyContent = 'space-between';
b.style.alignItems = 'center';
var l = document.createElement('span');
l.textContent = (p.best ? '⭐ ' : '') + p.titel;
var r = document.createElement('strong');
r.textContent = p.preis;
b.appendChild(l);
b.appendChild(r);
b.addEventListener('click', function () { starte(p.priceId, b); });
liste.appendChild(b);
});
function starte(priceId, knopf) {
if (!konsens.checked) {
fehler.style.display = 'block';
fehler.textContent = 'Bitte bestätigen Sie zuerst das Häkchen, um fortzufahren.';
konsens.focus();
return;
}
fehler.style.display = 'none';
var alt = knopf.innerHTML;
knopf.disabled = true;
knopf.textContent = 'Weiter zu Stripe …';
fetch(BASIS + '/kaufen', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ priceId: priceId }),
})
.then(function (r) { return r.json(); })
.then(function (d) { if (d && d.url) { window.location.href = d.url; return; } throw new Error('keine url'); })
.catch(function () {
knopf.disabled = false;
knopf.innerHTML = alt;
fehler.style.display = 'block';
fehler.textContent = 'Die Bezahlseite konnte nicht geöffnet werden. Bitte erneut versuchen.';
});
}
})();
</script>
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body>
</html>

View File

@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auf einen Behördenbrief antworten mit Muster | BehördenKlar</title>
<meta name="description" content="Ein Schreiben ans Amt aufsetzen: Wie Sie auf einen Behördenbrief richtig antworten Aufbau, Aktenzeichen, Frist und ein Muster-Text zum Abschreiben.">
<link rel="canonical" href="https://behoerdenklar.de/ratgeber/auf-behoerdenbrief-antworten">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="article">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.de/ratgeber/auf-behoerdenbrief-antworten">
<meta property="og:title" content="Auf einen Behördenbrief antworten mit Muster">
<meta property="og:description" content="Wie Sie ein Schreiben ans Amt richtig aufsetzen Aufbau, Aktenzeichen, Frist und Muster-Text.">
<meta property="og:image" content="https://behoerdenklar.de/vorschau.png">
<meta name="twitter:card" content="summary_large_image">
<style>
:root{--papier:#faf7f0;--tinte:#21211d;--grau:#6b675e;--amtsblau:#1d4e89;--marker:#ffe66b;--gruen:#2e7d4f;color-scheme:light}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:Georgia,'Times New Roman',serif;background:var(--papier);color:var(--tinte);line-height:1.75;font-size:18px}
.wrap{max-width:680px;margin:0 auto;padding:0 20px 60px}
a{color:var(--amtsblau)}
.top{display:flex;justify-content:space-between;align-items:baseline;padding:18px 0;border-bottom:2px solid var(--tinte);font-size:15px}
.top .marke{font-weight:700;text-decoration:none;color:var(--tinte)}
.brot{font-size:14px;color:var(--grau);margin:22px 0 0}
.brot a{color:var(--grau)}
.kicker{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--amtsblau);margin:8px 0 6px}
h1{font-size:clamp(27px,5vw,37px);line-height:1.2;margin-bottom:14px}
h2{font-size:23px;margin:32px 0 10px;line-height:1.25}
p{margin-bottom:16px}
ul,ol{margin:0 0 16px 22px}
li{margin-bottom:9px}
strong{font-weight:700}
.markiert{background:linear-gradient(104deg,transparent 2%,var(--marker) 4%,var(--marker) 96%,transparent 98%);padding:0 5px}
.kurz{background:#fff;border:2px solid var(--tinte);box-shadow:5px 6px 0 rgba(33,33,29,.9);padding:20px 22px;margin:26px 0}
.kurz h2{margin-top:0;font-size:18px;text-transform:uppercase;letter-spacing:.06em;color:var(--amtsblau)}
.kurz ul{margin-bottom:0}
.muster{background:#fff;border:1px dashed rgba(33,33,29,.5);padding:18px 20px;margin:18px 0;font-size:15.5px;line-height:1.7;white-space:pre-line}
.hinweis{font-size:15px;color:var(--grau);border-top:1px dashed rgba(33,33,29,.35);padding-top:14px;margin-top:30px}
.cta-box{background:var(--amtsblau);color:#fff;padding:24px 22px;margin:36px 0 0;border:2px solid var(--tinte);box-shadow:5px 6px 0 var(--tinte)}
.cta-box h2{color:#fff;margin:0 0 8px;font-size:22px}
.cta-box p{color:#e7effb;font-size:16px}
.cta-btn{display:inline-block;margin-top:6px;background:#fff;color:var(--amtsblau);font-weight:700;padding:13px 22px;text-decoration:none;border:2px solid var(--tinte)}
footer{margin-top:44px;padding-top:16px;border-top:2px solid var(--tinte);font-size:14px;color:var(--grau)}
footer a{color:var(--grau)}
</style>
<script type="application/ld+json">
{
"@context":"https://schema.org","@type":"FAQPage","mainEntity":[
{"@type":"Question","name":"Wie antworte ich richtig auf einen Behördenbrief?","acceptedAnswer":{"@type":"Answer","text":"Nennen Sie oben Ihr Aktenzeichen und den Bezug (Brief vom Datum), schreiben Sie klar und knapp, was Sie mitteilen oder beantragen, halten Sie die Frist ein und unterschreiben Sie. Schicken Sie wichtige Antworten nachweisbar, z. B. per Einschreiben, oder geben Sie sie persönlich ab."}},
{"@type":"Question","name":"Was muss in eine Antwort ans Amt hinein?","acceptedAnswer":{"@type":"Answer","text":"Ihr Name und Ihre Adresse, die Anschrift der Behörde, das Aktenzeichen, das Datum des Bezugsschreibens, Ihr Anliegen in klaren Worten sowie Datum und Unterschrift. Fügen Sie angeforderte Nachweise als Kopie bei."}},
{"@type":"Question","name":"Was passiert, wenn ich die Frist verpasse?","acceptedAnswer":{"@type":"Answer","text":"Dann kann eine Entscheidung endgültig (bestandskräftig) werden oder es drohen Nachteile, etwa Leistungskürzungen. Reagieren Sie deshalb rechtzeitig. Wenn Sie mehr Zeit brauchen, bitten Sie die Behörde vor Ablauf der Frist schriftlich um eine Fristverlängerung."}}
]
}
</script>
</head>
<body>
<div class="wrap">
<div class="top">
<a class="marke" href="/">📬 BehördenKlar</a>
<a href="/ratgeber/">Ratgeber</a>
</div>
<p class="brot"><a href="/">Start</a> <a href="/ratgeber/">Ratgeber</a> Auf einen Behördenbrief antworten</p>
<p class="kicker">Ratgeber · Antworten</p>
<h1>Auf einen Behördenbrief <span class="markiert">richtig antworten</span></h1>
<p>
Die Behörde will etwas von Ihnen — eine Auskunft, Unterlagen oder eine
Stellungnahme. Viele schieben die Antwort auf, weil sie nicht wissen,
<strong>wie man ans Amt schreibt</strong>. Dabei ist es einfacher, als es
aussieht. Hier steht, wie Sie <strong>auf einen Behördenbrief antworten</strong>
mit einem <strong>Muster zum Abschreiben</strong>.
</p>
<div class="kurz">
<h2>Das Wichtigste in Kürze</h2>
<ul>
<li>Immer das <strong>Aktenzeichen</strong> und das <strong>Datum</strong> des Briefs angeben.</li>
<li><strong>Klar und knapp</strong> schreiben — kein schönes Amtsdeutsch nötig.</li>
<li>Die <strong>Frist einhalten</strong> — im Zweifel vorher um Verlängerung bitten.</li>
<li>Wichtige Antworten <strong>nachweisbar</strong> schicken (Einschreiben) oder persönlich abgeben.</li>
</ul>
</div>
<h2>Der Aufbau einer Antwort</h2>
<ol>
<li><strong>Ihre Angaben</strong> oben: Name, Adresse.</li>
<li><strong>Anschrift der Behörde</strong> (steht im Brief).</li>
<li><strong>Ort und Datum.</strong></li>
<li><strong>Aktenzeichen</strong> und Bezug: „Ihr Schreiben vom [Datum]".</li>
<li><strong>Ihr Anliegen</strong> in klaren Sätzen: Was teilen Sie mit? Was beantragen Sie?</li>
<li><strong>Anlagen</strong> nennen (Kopien der geforderten Nachweise).</li>
<li><strong>Gruß und Unterschrift.</strong></li>
</ol>
<h2>Muster: Antwort ans Amt</h2>
<div class="muster">Max Mustermann
Musterstraße 12
67722 Winnweiler
[Behörde und Anschrift]
Ort, Datum
Aktenzeichen: [Ihr Aktenzeichen]
Betreff: Ihr Schreiben vom [Datum]
Sehr geehrte Damen und Herren,
vielen Dank für Ihr Schreiben. Zu Ihrer Aufforderung teile ich Ihnen
Folgendes mit:
[Ihr Anliegen — z. B. „Anbei sende ich die angeforderten Unterlagen"
oder „Ich bitte um Verlängerung der Frist bis zum …, weil …"].
Anlagen: [z. B. Kopie Lohnabrechnung, Mietvertrag]
Mit freundlichen Grüßen
[Unterschrift]
Max Mustermann</div>
<h2>Sie brauchen mehr Zeit? Fristverlängerung</h2>
<p>
Wenn Sie die Frist nicht schaffen, bitten Sie die Behörde <strong>vor
Ablauf</strong> schriftlich um eine <strong>Fristverlängerung</strong> und
nennen Sie kurz den Grund. Das ist in vielen Fällen möglich — aber nur, wenn
Sie sich rechtzeitig melden.
</p>
<h2>Häufige Fehler vermeiden</h2>
<ul>
<li><strong>Aktenzeichen vergessen</strong> — die Behörde kann den Brief dann kaum zuordnen.</li>
<li><strong>Zu spät</strong> — die Frist ist das Wichtigste.</li>
<li><strong>Originale verschickt</strong> — immer nur <strong>Kopien</strong> von Nachweisen senden.</li>
<li><strong>Kein Nachweis</strong> — bei Wichtigem per Einschreiben oder persönlich mit Eingangsstempel.</li>
</ul>
<p class="hinweis">
⚖️ Dieser Ratgeber erklärt allgemein und ersetzt keine Rechtsberatung. Bei
wichtigen Entscheidungen wenden Sie sich an eine Beratungsstelle, einen
Sozialverband oder eine Anwältin bzw. einen Anwalt.
</p>
<div class="cta-box">
<h2>Antwort-Entwurf per Foto</h2>
<p>
BehördenKlar erklärt Ihren Brief in einfacher Sprache und hilft Ihnen,
eine passende Antwort zu formulieren — mit Aktenzeichen und Frist im Blick.
Kostenlos im Browser testen.
</p>
<a class="cta-btn" href="/demo">Jetzt gratis testen →</a>
</div>
<footer>
<a href="/ratgeber/">← Zurück zum Ratgeber</a> ·
<a href="/">Startseite</a> ·
<a href="/impressum.html">Impressum</a> ·
<a href="/datenschutz.html">Datenschutz</a>
</footer>
</div>
<!-- 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

@@ -0,0 +1,163 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Behördenbrief übersetzen in 9 Sprachen verstehen | BehördenKlar</title>
<meta name="description" content="Einen Behördenbrief übersetzen und verstehen: So bekommen Sie Amtspost in Ihrer Sprache erklärt Arabisch, Türkisch, Ukrainisch, Russisch und mehr. Einfach per Foto.">
<link rel="canonical" href="https://behoerdenklar.de/ratgeber/behoerdenbrief-uebersetzen">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="article">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.de/ratgeber/behoerdenbrief-uebersetzen">
<meta property="og:title" content="Behördenbrief übersetzen in 9 Sprachen verstehen">
<meta property="og:description" content="Amtspost in Ihrer Sprache erklärt: Arabisch, Türkisch, Ukrainisch, Russisch und mehr einfach per Foto.">
<meta property="og:image" content="https://behoerdenklar.de/vorschau.png">
<meta name="twitter:card" content="summary_large_image">
<style>
:root{--papier:#faf7f0;--tinte:#21211d;--grau:#6b675e;--amtsblau:#1d4e89;--marker:#ffe66b;--gruen:#2e7d4f;color-scheme:light}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:Georgia,'Times New Roman',serif;background:var(--papier);color:var(--tinte);line-height:1.75;font-size:18px}
.wrap{max-width:680px;margin:0 auto;padding:0 20px 60px}
a{color:var(--amtsblau)}
.top{display:flex;justify-content:space-between;align-items:baseline;padding:18px 0;border-bottom:2px solid var(--tinte);font-size:15px}
.top .marke{font-weight:700;text-decoration:none;color:var(--tinte)}
.brot{font-size:14px;color:var(--grau);margin:22px 0 0}
.brot a{color:var(--grau)}
.kicker{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--amtsblau);margin:8px 0 6px}
h1{font-size:clamp(27px,5vw,37px);line-height:1.2;margin-bottom:14px}
h2{font-size:23px;margin:32px 0 10px;line-height:1.25}
p{margin-bottom:16px}
ul,ol{margin:0 0 16px 22px}
li{margin-bottom:9px}
strong{font-weight:700}
.markiert{background:linear-gradient(104deg,transparent 2%,var(--marker) 4%,var(--marker) 96%,transparent 98%);padding:0 5px}
.kurz{background:#fff;border:2px solid var(--tinte);box-shadow:5px 6px 0 rgba(33,33,29,.9);padding:20px 22px;margin:26px 0}
.kurz h2{margin-top:0;font-size:18px;text-transform:uppercase;letter-spacing:.06em;color:var(--amtsblau)}
.kurz ul{margin-bottom:0}
.sprachen{display:flex;flex-wrap:wrap;gap:8px;margin:6px 0 20px;padding:0;list-style:none}
.sprachen li{margin:0;background:#fff;border:1px solid rgba(33,33,29,.3);padding:6px 12px;font-size:15px}
.hinweis{font-size:15px;color:var(--grau);border-top:1px dashed rgba(33,33,29,.35);padding-top:14px;margin-top:30px}
.cta-box{background:var(--amtsblau);color:#fff;padding:24px 22px;margin:36px 0 0;border:2px solid var(--tinte);box-shadow:5px 6px 0 var(--tinte)}
.cta-box h2{color:#fff;margin:0 0 8px;font-size:22px}
.cta-box p{color:#e7effb;font-size:16px}
.cta-btn{display:inline-block;margin-top:6px;background:#fff;color:var(--amtsblau);font-weight:700;padding:13px 22px;text-decoration:none;border:2px solid var(--tinte)}
footer{margin-top:44px;padding-top:16px;border-top:2px solid var(--tinte);font-size:14px;color:var(--grau)}
footer a{color:var(--grau)}
</style>
<script type="application/ld+json">
{
"@context":"https://schema.org","@type":"FAQPage","mainEntity":[
{"@type":"Question","name":"Wie kann ich einen Behördenbrief übersetzen?","acceptedAnswer":{"@type":"Answer","text":"Sie können den Brief fotografieren und mit BehördenKlar in einfacher Sprache erklären und in Ihre Sprache übersetzen lassen z. B. Arabisch, Türkisch, Ukrainisch oder Russisch. Wichtig: Es geht nicht nur um eine Wort-für-Wort-Übersetzung, sondern darum, zu verstehen, was der Brief bedeutet und was zu tun ist."}},
{"@type":"Question","name":"Ist eine automatische Übersetzung von Amtspost sicher genug?","acceptedAnswer":{"@type":"Answer","text":"Eine Übersetzung hilft beim Verstehen. Bei rechtlich wichtigen Entscheidungen (z. B. Fristen, Widerspruch) sollten Sie zusätzlich eine Beratungsstelle oder eine Anwältin bzw. einen Anwalt fragen. Verlassen Sie sich bei Fristen immer auch auf das Datum im Originalbrief."}},
{"@type":"Question","name":"Welche Sprachen werden unterstützt?","acceptedAnswer":{"@type":"Answer","text":"BehördenKlar erklärt Briefe unter anderem auf Deutsch, Englisch, Türkisch, Arabisch, Ukrainisch, Russisch, Polnisch, Französisch und Spanisch."}}
]
}
</script>
</head>
<body>
<div class="wrap">
<div class="top">
<a class="marke" href="/">📬 BehördenKlar</a>
<a href="/ratgeber/">Ratgeber</a>
</div>
<p class="brot"><a href="/">Start</a> <a href="/ratgeber/">Ratgeber</a> Behördenbrief übersetzen</p>
<p class="kicker">Ratgeber · Übersetzen</p>
<h1>Behördenbrief <span class="markiert">übersetzen und verstehen</span></h1>
<p>
Ein Brief vom Amt ist schon auf Deutsch schwer — und noch schwerer, wenn
Deutsch nicht Ihre Muttersprache ist. Ein <strong>Wörterbuch reicht oft
nicht</strong>, weil das Problem nicht einzelne Wörter sind, sondern das
<strong>Amtsdeutsch</strong>: lange Sätze, Paragrafen, versteckte Fristen.
Hier erfahren Sie, wie Sie einen <strong>Behördenbrief übersetzen</strong>
und vor allem <strong>verstehen</strong>, was zu tun ist.
</p>
<div class="kurz">
<h2>Das Wichtigste in Kürze</h2>
<ul>
<li>Sie müssen Amtspost nicht Wort für Wort übersetzen — wichtig ist, <strong>was gemeint ist</strong> und <strong>bis wann</strong> Sie handeln müssen.</li>
<li>Fotografieren Sie den Brief — BehördenKlar erklärt ihn in <strong>einfacher Sprache</strong> und in Ihrer Sprache.</li>
<li>Achten Sie besonders auf <strong>Fristen und Termine</strong> — die stehen oft klein im Text.</li>
<li>Bei wichtigen Sachen zusätzlich eine <strong>Beratungsstelle</strong> fragen (kostenlos, in vielen Sprachen).</li>
</ul>
</div>
<h2>Warum ein normaler Übersetzer oft nicht reicht</h2>
<p>
Automatische Wort-Übersetzer geben Ihnen die Wörter in Ihrer Sprache — aber
der Sinn bleibt oft unklar. „Mitwirkungspflicht", „Rechtsbehelfsbelehrung"
oder „Bestandskraft" ergeben auch übersetzt selten Sinn, wenn niemand
erklärt, <strong>was die Behörde konkret von Ihnen will</strong>. Genau das
ist der Unterschied: Es geht nicht ums Übersetzen einzelner Wörter, sondern
ums <strong>Verständlich-Machen</strong>.
</p>
<h2>In diesen Sprachen bekommen Sie den Brief erklärt</h2>
<p>BehördenKlar erklärt Behördenbriefe unter anderem in:</p>
<ul class="sprachen">
<li>🇩🇪 Deutsch</li>
<li>🇬🇧 Englisch</li>
<li>🇹🇷 Türkisch</li>
<li>🇸🇦 Arabisch</li>
<li>🇺🇦 Ukrainisch</li>
<li>🇷🇺 Russisch</li>
<li>🇵🇱 Polnisch</li>
<li>🇫🇷 Französisch</li>
<li>🇪🇸 Spanisch</li>
</ul>
<h2>So übersetzen und verstehen Sie den Brief — Schritt für Schritt</h2>
<ol>
<li><strong>Foto machen:</strong> Fotografieren Sie den ganzen Brief bei gutem Licht (oder laden Sie ihn als PDF hoch).</li>
<li><strong>Sprache wählen:</strong> Sie bekommen die Erklärung in Ihrer Sprache.</li>
<li><strong>Klartext lesen:</strong> Was bedeutet der Brief? Was will die Behörde?</li>
<li><strong>Frist prüfen:</strong> Bis wann müssen Sie reagieren? Gleichen Sie das Datum mit dem Originalbrief ab.</li>
<li><strong>Antworten:</strong> Wenn nötig, hilft Ihnen die App auch bei einer passenden Antwort.</li>
</ol>
<h2>Wichtig bei Fristen</h2>
<p>
Eine Übersetzung hilft beim Verstehen — aber <strong>bei Fristen zählt das
Original</strong>. Prüfen Sie das genaue Datum immer im echten Brief nach.
Verpassen Sie eine Frist, kann eine Entscheidung <strong>endgültig</strong>
werden. Im Zweifel lieber früher bei einer Beratungsstelle nachfragen.
</p>
<h2>Wo bekomme ich zusätzlich Hilfe?</h2>
<ul>
<li><strong>Migrationsberatung (MBE)</strong> und <strong>Jugendmigrationsdienste</strong> beraten kostenlos, oft mehrsprachig.</li>
<li><strong>Wohlfahrtsverbände</strong> (Caritas, Diakonie, AWO, DRK) helfen beim Verstehen und Ausfüllen.</li>
<li><strong>Integrationslotsen</strong> und Vereine vor Ort begleiten zu Terminen.</li>
</ul>
<p class="hinweis">
⚖️ Dieser Ratgeber erklärt allgemein und ersetzt keine Rechtsberatung. Eine
Übersetzung ist eine Verständnishilfe. Bei wichtigen Entscheidungen wenden
Sie sich an eine Beratungsstelle oder eine Anwältin bzw. einen Anwalt.
</p>
<div class="cta-box">
<h2>Brief in Ihrer Sprache erklärt</h2>
<p>
Fotografieren Sie Ihren Behördenbrief — BehördenKlar erklärt ihn in
einfacher Sprache und in Ihrer Sprache, findet Fristen und hilft beim
Antworten. Kostenlos im Browser testen.
</p>
<a class="cta-btn" href="/demo">Jetzt gratis testen →</a>
</div>
<footer>
<a href="/ratgeber/">← Zurück zum Ratgeber</a> ·
<a href="/">Startseite</a> ·
<a href="/impressum.html">Impressum</a> ·
<a href="/datenschutz.html">Datenschutz</a>
</footer>
</div>
<!-- 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

@@ -0,0 +1,150 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Behördenbrief verstehen Amtsdeutsch einfach erklärt | BehördenKlar</title>
<meta name="description" content="Behördenbrief nicht verstanden? So übersetzen Sie Amtsdeutsch in Klartext: die wichtigsten Wörter erklärt, worauf Sie achten müssen und wie Sie richtig reagieren.">
<link rel="canonical" href="https://behoerdenklar.de/ratgeber/behoerdenbrief-verstehen">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="article">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.de/ratgeber/behoerdenbrief-verstehen">
<meta property="og:title" content="Behördenbrief verstehen Amtsdeutsch einfach erklärt">
<meta property="og:description" content="Amtsdeutsch in Klartext: die wichtigsten Wörter erklärt und wie Sie richtig reagieren.">
<meta property="og:image" content="https://behoerdenklar.de/vorschau.png">
<meta name="twitter:card" content="summary_large_image">
<style>
:root{--papier:#faf7f0;--tinte:#21211d;--grau:#6b675e;--amtsblau:#1d4e89;--marker:#ffe66b;--gruen:#2e7d4f;color-scheme:light}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:Georgia,'Times New Roman',serif;background:var(--papier);color:var(--tinte);line-height:1.75;font-size:18px}
.wrap{max-width:680px;margin:0 auto;padding:0 20px 60px}
a{color:var(--amtsblau)}
.top{display:flex;justify-content:space-between;align-items:baseline;padding:18px 0;border-bottom:2px solid var(--tinte);font-size:15px}
.top .marke{font-weight:700;text-decoration:none;color:var(--tinte)}
.brot{font-size:14px;color:var(--grau);margin:22px 0 0}
.brot a{color:var(--grau)}
.kicker{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--amtsblau);margin:8px 0 6px}
h1{font-size:clamp(27px,5vw,37px);line-height:1.2;margin-bottom:14px}
h2{font-size:23px;margin:32px 0 10px;line-height:1.25}
p{margin-bottom:16px}
ul,ol{margin:0 0 16px 22px}
li{margin-bottom:9px}
strong{font-weight:700}
.markiert{background:linear-gradient(104deg,transparent 2%,var(--marker) 4%,var(--marker) 96%,transparent 98%);padding:0 5px}
.kurz{background:#fff;border:2px solid var(--tinte);box-shadow:5px 6px 0 rgba(33,33,29,.9);padding:20px 22px;margin:26px 0}
.kurz h2{margin-top:0;font-size:18px;text-transform:uppercase;letter-spacing:.06em;color:var(--amtsblau)}
.kurz ul{margin-bottom:0}
.glossar{list-style:none;margin:6px 0 16px;padding:0}
.glossar li{background:#fff;border:1px solid rgba(33,33,29,.28);padding:12px 16px;margin-bottom:10px}
.glossar b{color:var(--amtsblau)}
.hinweis{font-size:15px;color:var(--grau);border-top:1px dashed rgba(33,33,29,.35);padding-top:14px;margin-top:30px}
.cta-box{background:var(--amtsblau);color:#fff;padding:24px 22px;margin:36px 0 0;border:2px solid var(--tinte);box-shadow:5px 6px 0 var(--tinte)}
.cta-box h2{color:#fff;margin:0 0 8px;font-size:22px}
.cta-box p{color:#e7effb;font-size:16px}
.cta-btn{display:inline-block;margin-top:6px;background:#fff;color:var(--amtsblau);font-weight:700;padding:13px 22px;text-decoration:none;border:2px solid var(--tinte)}
footer{margin-top:44px;padding-top:16px;border-top:2px solid var(--tinte);font-size:14px;color:var(--grau)}
footer a{color:var(--grau)}
</style>
<script type="application/ld+json">
{
"@context":"https://schema.org","@type":"FAQPage","mainEntity":[
{"@type":"Question","name":"Was mache ich, wenn ich einen Behördenbrief nicht verstehe?","acceptedAnswer":{"@type":"Answer","text":"Lesen Sie zuerst den Betreff und suchen Sie nach einem Datum oder einer Frist. Lassen Sie sich den Brief in einfacher Sprache erklären z. B. mit BehördenKlar per Foto und fragen Sie bei Bedarf eine kostenlose Beratungsstelle. Ignorieren ist das Schlechteste, weil Fristen ablaufen können."}},
{"@type":"Question","name":"Was bedeutet 'Rechtsbehelfsbelehrung'?","acceptedAnswer":{"@type":"Answer","text":"Das ist der Abschnitt am Ende eines Bescheids, der erklärt, wie und bis wann Sie sich gegen die Entscheidung wehren können (z. B. Widerspruch oder Klage) und bei welcher Stelle. Dort steht Ihre wichtigste Frist."}},
{"@type":"Question","name":"Muss ich auf jeden Behördenbrief antworten?","acceptedAnswer":{"@type":"Answer","text":"Nicht auf jeden. Reine Informationsschreiben brauchen keine Antwort. Sobald aber eine Frist, eine Aufforderung oder ein Termin genannt wird, sollten Sie reagieren. Prüfen Sie den Brief deshalb immer auf Fristen."}}
]
}
</script>
</head>
<body>
<div class="wrap">
<div class="top">
<a class="marke" href="/">📬 BehördenKlar</a>
<a href="/ratgeber/">Ratgeber</a>
</div>
<p class="brot"><a href="/">Start</a> <a href="/ratgeber/">Ratgeber</a> Behördenbrief verstehen</p>
<p class="kicker">Ratgeber · Verstehen</p>
<h1>Behördenbrief verstehen — <span class="markiert">Amtsdeutsch in Klartext</span></h1>
<p>
„Gemäß § 32 SGB II wird bei Nichterscheinen ohne wichtigen Grund eine
Minderung des maßgebenden Regelbedarfs festgestellt." — Sätze wie dieser
sind der Grund, warum so viele Menschen Amtspost nicht verstehen. Das
Problem ist das <strong>Amtsdeutsch</strong>. Hier lernen Sie, wie Sie einen
<strong>Behördenbrief verstehen</strong> und in <strong>Klartext</strong>
übersetzen.
</p>
<div class="kurz">
<h2>Das Wichtigste in Kürze</h2>
<ul>
<li>Lesen Sie zuerst <strong>Betreff</strong> und suchen Sie nach einem <strong>Datum / einer Frist</strong>.</li>
<li>Fragen Sie sich: <strong>Was will die Behörde von mir?</strong> und <strong>bis wann?</strong></li>
<li><strong>Nicht ignorieren</strong> — abgelaufene Fristen sind das teuerste Problem.</li>
<li>Lassen Sie sich den Brief in <strong>einfacher Sprache</strong> erklären, wenn er unklar ist.</li>
</ul>
</div>
<h2>So gehen Sie einen Brief durch</h2>
<ol>
<li><strong>Absender:</strong> Welche Behörde? (Jobcenter, Finanzamt, Ausländerbehörde …)</li>
<li><strong>Betreff / Überschrift:</strong> gibt meist das Thema vor.</li>
<li><strong>Frist oder Termin:</strong> Suchen Sie nach Datumsangaben und Wörtern wie „bis", „innerhalb", „spätestens".</li>
<li><strong>Aufforderung:</strong> Was sollen Sie tun oder schicken?</li>
<li><strong>Rechtsbehelfsbelehrung</strong> (ganz unten): Wie können Sie sich wehren, bis wann?</li>
</ol>
<h2>Die wichtigsten Amtswörter — kurz erklärt</h2>
<ul class="glossar">
<li><b>Bescheid</b> — eine offizielle Entscheidung der Behörde (z. B. über Geld oder einen Antrag).</li>
<li><b>Frist</b> — der Zeitpunkt, bis zu dem Sie etwas tun müssen.</li>
<li><b>Mitwirkungspflicht</b> — Sie müssen mithelfen, z. B. Unterlagen einreichen.</li>
<li><b>Rechtsbehelfsbelehrung</b> — erklärt, wie und bis wann Sie Widerspruch/Klage einlegen können.</li>
<li><b>Widerspruch</b> — Ihre Möglichkeit, eine Entscheidung noch einmal prüfen zu lassen.</li>
<li><b>Bestandskraft</b> — der Bescheid ist endgültig, weil die Frist abgelaufen ist.</li>
<li><b>Aktenzeichen</b> — die Nummer Ihres Vorgangs; immer angeben, wenn Sie antworten.</li>
</ul>
<h2>Was, wenn ich es trotzdem nicht verstehe?</h2>
<p>
Kein Grund zur Sorge — dafür gibt es Hilfe. Sie können sich den Brief in
<strong>einfacher Sprache erklären lassen</strong> (z. B. per Foto mit
BehördenKlar) oder eine <strong>Beratungsstelle</strong> fragen. Wichtig ist
nur: <strong>reagieren Sie rechtzeitig</strong>, statt den Brief wegzulegen.
</p>
<h2>Wo bekomme ich Hilfe?</h2>
<ul>
<li><strong>Wohlfahrtsverbände</strong> (Caritas, Diakonie, AWO, DRK) — kostenlose Beratung.</li>
<li><strong>Sozialverbände</strong> (VdK, SoVD) — besonders im Sozialrecht.</li>
<li><strong>Migrationsberatung</strong> — oft mehrsprachig.</li>
</ul>
<p class="hinweis">
⚖️ Dieser Ratgeber erklärt allgemein und ersetzt keine Rechtsberatung. Bei
wichtigen Entscheidungen wenden Sie sich an eine Beratungsstelle oder eine
Anwältin bzw. einen Anwalt.
</p>
<div class="cta-box">
<h2>Brief nicht verstanden? Foto genügt</h2>
<p>
BehördenKlar übersetzt Amtsdeutsch in Klartext: fotografieren, verstehen,
Frist erkennen, richtig reagieren. Kostenlos im Browser testen.
</p>
<a class="cta-btn" href="/demo">Jetzt gratis testen →</a>
</div>
<footer>
<a href="/ratgeber/">← Zurück zum Ratgeber</a> ·
<a href="/">Startseite</a> ·
<a href="/impressum.html">Impressum</a> ·
<a href="/datenschutz.html">Datenschutz</a>
</footer>
</div>
<!-- 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

@@ -0,0 +1,168 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Behördenpost organisieren Fristen und Briefe im Blick | BehördenKlar</title>
<meta name="description" content="Behördenbriefe organisieren, ohne Frist zu verpassen: ein einfaches System zum Sortieren, Ablegen und Erinnern mit Checkliste. So behalten Sie Amtspost im Griff.">
<link rel="canonical" href="https://behoerdenklar.de/ratgeber/behoerdenpost-organisieren">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="article">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.de/ratgeber/behoerdenpost-organisieren">
<meta property="og:title" content="Behördenpost organisieren Fristen und Briefe im Blick">
<meta property="og:description" content="Ein einfaches System zum Sortieren, Ablegen und Erinnern damit Sie keine Frist mehr verpassen.">
<meta property="og:image" content="https://behoerdenklar.de/vorschau.png">
<meta name="twitter:card" content="summary_large_image">
<style>
:root{--papier:#faf7f0;--tinte:#21211d;--grau:#6b675e;--amtsblau:#1d4e89;--marker:#ffe66b;--gruen:#2e7d4f;color-scheme:light}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:Georgia,'Times New Roman',serif;background:var(--papier);color:var(--tinte);line-height:1.75;font-size:18px}
.wrap{max-width:680px;margin:0 auto;padding:0 20px 60px}
a{color:var(--amtsblau)}
.top{display:flex;justify-content:space-between;align-items:baseline;padding:18px 0;border-bottom:2px solid var(--tinte);font-size:15px}
.top .marke{font-weight:700;text-decoration:none;color:var(--tinte)}
.brot{font-size:14px;color:var(--grau);margin:22px 0 0}
.brot a{color:var(--grau)}
.kicker{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--amtsblau);margin:8px 0 6px}
h1{font-size:clamp(27px,5vw,37px);line-height:1.2;margin-bottom:14px}
h2{font-size:23px;margin:32px 0 10px;line-height:1.25}
p{margin-bottom:16px}
ul,ol{margin:0 0 16px 22px}
li{margin-bottom:9px}
strong{font-weight:700}
.markiert{background:linear-gradient(104deg,transparent 2%,var(--marker) 4%,var(--marker) 96%,transparent 98%);padding:0 5px}
.kurz{background:#fff;border:2px solid var(--tinte);box-shadow:5px 6px 0 rgba(33,33,29,.9);padding:20px 22px;margin:26px 0}
.kurz h2{margin-top:0;font-size:18px;text-transform:uppercase;letter-spacing:.06em;color:var(--amtsblau)}
.kurz ul{margin-bottom:0}
.ampel{background:#fff;border:1px solid rgba(33,33,29,.28);padding:16px 20px;margin:18px 0}
.ampel p{margin:6px 0}
.hinweis{font-size:15px;color:var(--grau);border-top:1px dashed rgba(33,33,29,.35);padding-top:14px;margin-top:30px}
.cta-box{background:var(--amtsblau);color:#fff;padding:24px 22px;margin:36px 0 0;border:2px solid var(--tinte);box-shadow:5px 6px 0 var(--tinte)}
.cta-box h2{color:#fff;margin:0 0 8px;font-size:22px}
.cta-box p{color:#e7effb;font-size:16px}
.cta-btn{display:inline-block;margin-top:6px;background:#fff;color:var(--amtsblau);font-weight:700;padding:13px 22px;text-decoration:none;border:2px solid var(--tinte)}
footer{margin-top:44px;padding-top:16px;border-top:2px solid var(--tinte);font-size:14px;color:var(--grau)}
footer a{color:var(--grau)}
</style>
<script type="application/ld+json">
{
"@context":"https://schema.org","@type":"FAQPage","mainEntity":[
{"@type":"Question","name":"Wie organisiere ich meine Behördenpost am besten?","acceptedAnswer":{"@type":"Answer","text":"Legen Sie jeden Brief sofort an einen festen Platz, notieren Sie die Frist in einem Kalender und sortieren Sie nach 'erledigt' und 'offen'. Wichtig ist ein fester Ablauf: öffnen, Frist notieren, ablegen. Digital hilft ein Foto-Archiv mit Erinnerung an Fristen."}},
{"@type":"Question","name":"Wie lange muss ich Behördenbriefe aufbewahren?","acceptedAnswer":{"@type":"Answer","text":"Wichtige Bescheide (z. B. Rente, Steuer, Sozialleistungen) sollten Sie langfristig aufbewahren. Als Faustregel gelten mindestens die Fristen, in denen Ansprüche oder Nachweise relevant sein können. Im Zweifel lieber behalten und einscannen."}},
{"@type":"Question","name":"Was tun, wenn ich viele Briefe auf einmal habe?","acceptedAnswer":{"@type":"Answer","text":"Sortieren Sie zuerst nach Dringlichkeit: Gibt es eine Frist? Fangen Sie mit den Briefen an, bei denen bald etwas fällig ist. Briefe ohne Frist können warten. Ein Foto-Archiv mit Frist-Erkennung hilft, den Überblick zu behalten."}}
]
}
</script>
</head>
<body>
<div class="wrap">
<div class="top">
<a class="marke" href="/">📬 BehördenKlar</a>
<a href="/ratgeber/">Ratgeber</a>
</div>
<p class="brot"><a href="/">Start</a> <a href="/ratgeber/">Ratgeber</a> Behördenpost organisieren</p>
<p class="kicker">Ratgeber · Organisieren</p>
<h1>Behördenpost <span class="markiert">organisieren, ohne Frist zu verpassen</span></h1>
<p>
Ein Stapel Briefe vom Amt, jeder mit einem anderen Datum — und die Angst,
etwas Wichtiges zu übersehen. Das teuerste Problem bei Amtspost ist nicht
der einzelne Brief, sondern der <strong>Überblick</strong>. Hier ist ein
einfaches System, mit dem Sie Ihre <strong>Behördenbriefe organisieren</strong>
und <strong>keine Frist mehr verpassen</strong>.
</p>
<div class="kurz">
<h2>Das Wichtigste in Kürze</h2>
<ul>
<li>Fester Ablauf: <strong>öffnen → Frist notieren → ablegen</strong>. Jeder Brief, jedes Mal gleich.</li>
<li>Ein <strong>fester Platz</strong> für Amtspost — nicht mal hier, mal dort.</li>
<li>Trennen Sie <strong>„offen"</strong> (noch zu tun) von <strong>„erledigt"</strong>.</li>
<li>Fristen gehören <strong>in einen Kalender mit Erinnerung</strong> — nicht in den Kopf.</li>
</ul>
</div>
<h2>Schritt 1: Ein fester Ablauf für jeden Brief</h2>
<p>
Nehmen Sie sich für jeden Brief kurz drei Handgriffe vor — immer dieselben:
</p>
<ol>
<li><strong>Öffnen und lesen:</strong> Worum geht es? Was will die Behörde?</li>
<li><strong>Frist notieren:</strong> Steht ein Datum drin? Sofort in den Kalender.</li>
<li><strong>Ablegen:</strong> An den festen Platz — offen oder erledigt.</li>
</ol>
<p>
Dieser kleine Ablauf verhindert das Häufigste: Briefe, die ungeöffnet liegen
bleiben, bis die Frist vorbei ist.
</p>
<h2>Schritt 2: Zwei Stapel — offen und erledigt</h2>
<p>
Sie brauchen kein kompliziertes System. Zwei Ablagen reichen:
</p>
<ul>
<li><strong>Offen:</strong> Hier braucht es noch eine Reaktion (antworten, Unterlagen schicken, Termin).</li>
<li><strong>Erledigt:</strong> Aufbewahren als Nachweis, aber nichts mehr zu tun.</li>
</ul>
<p>
Wer digital arbeitet, fotografiert die Briefe und legt sie in zwei Ordnern
auf dem Handy ab — so hat man sie auch beim Termin dabei.
</p>
<h2>Schritt 3: Nach Dringlichkeit sortieren (Ampel-Prinzip)</h2>
<p>
Wenn viel auf einmal kommt, sortieren Sie nach der Frist — nicht nach dem
Eingangsdatum:
</p>
<div class="ampel">
<p>🔴 <strong>Rot — bald fällig (in wenigen Tagen):</strong> zuerst erledigen.</p>
<p>🟡 <strong>Gelb — mittelfristig (23 Wochen):</strong> einplanen.</p>
<p>🟢 <strong>Grün — keine oder ferne Frist:</strong> kann warten, aber ablegen.</p>
</div>
<h2>Schritt 4: Fristen aus dem Kopf in den Kalender</h2>
<p>
Merken Sie sich Fristen <strong>nicht</strong> — tragen Sie sie ein. Am
besten mit einer <strong>Erinnerung ein paar Tage vorher</strong>, damit Sie
noch Zeit zum Reagieren haben. Die wichtigste Frist steht oft klein in der
<strong>Rechtsbehelfsbelehrung</strong> am Ende des Briefs.
</p>
<h2>Was tun mit alten Briefen?</h2>
<p>
Wichtige Bescheide (Rente, Steuer, Sozialleistungen, Aufenthalt) gehören
langfristig aufbewahrt — am besten zusätzlich <strong>eingescannt</strong>,
falls das Papier verloren geht. Reine Infoschreiben ohne Bedeutung können
Sie aussortieren.
</p>
<p class="hinweis">
⚖️ Dieser Ratgeber erklärt allgemein und ersetzt keine Rechtsberatung. Bei
wichtigen Entscheidungen wenden Sie sich an eine Beratungsstelle oder eine
Anwältin bzw. einen Anwalt.
</p>
<div class="cta-box">
<h2>Fristen automatisch im Blick</h2>
<p>
Fotografieren Sie Ihre Briefe — BehördenKlar erklärt sie in einfacher
Sprache und erkennt Fristen und Termine, damit Sie nichts verpassen.
Kostenlos im Browser testen.
</p>
<a class="cta-btn" href="/demo">Jetzt gratis testen →</a>
</div>
<footer>
<a href="/ratgeber/">← Zurück zum Ratgeber</a> ·
<a href="/">Startseite</a> ·
<a href="/impressum.html">Impressum</a> ·
<a href="/datenschutz.html">Datenschutz</a>
</footer>
</div>
<!-- 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

@@ -76,6 +76,30 @@
<span>Welche Frist gilt, wie Sie einen Widerspruch schreiben mit Muster-Text zum Abschreiben.</span>
</a>
</li>
<li>
<a class="artikel-karte" href="/ratgeber/behoerdenbrief-verstehen">
<b>Behördenbrief verstehen Amtsdeutsch in Klartext</b>
<span>Wie Sie einen Brief vom Amt Schritt für Schritt durchgehen mit den wichtigsten Amtswörtern erklärt.</span>
</a>
</li>
<li>
<a class="artikel-karte" href="/ratgeber/behoerdenbrief-uebersetzen">
<b>Behördenbrief übersetzen in 9 Sprachen</b>
<span>Amtspost in Ihrer Sprache erklärt: Arabisch, Türkisch, Ukrainisch und mehr einfach per Foto.</span>
</a>
</li>
<li>
<a class="artikel-karte" href="/ratgeber/behoerdenpost-organisieren">
<b>Behördenpost organisieren</b>
<span>Ein einfaches System zum Sortieren, Ablegen und Erinnern damit Sie keine Frist verpassen.</span>
</a>
</li>
<li>
<a class="artikel-karte" href="/ratgeber/auf-behoerdenbrief-antworten">
<b>Auf einen Behördenbrief antworten</b>
<span>Wie Sie ein Schreiben ans Amt aufsetzen Aufbau, Aktenzeichen, Frist und Muster zum Abschreiben.</span>
</a>
</li>
</ul>
<footer>

View File

@@ -13,4 +13,8 @@
<url><loc>https://behoerdenklar.de/ratgeber/steuerbescheid-finanzamt-einspruch</loc><lastmod>2026-07-25</lastmod></url>
<url><loc>https://behoerdenklar.de/ratgeber/auslaenderbehoerde-termin-aufenthaltstitel</loc><lastmod>2026-07-25</lastmod></url>
<url><loc>https://behoerdenklar.de/ratgeber/widerspruch-einlegen</loc><lastmod>2026-07-25</lastmod></url>
<url><loc>https://behoerdenklar.de/ratgeber/behoerdenbrief-verstehen</loc><lastmod>2026-08-19</lastmod></url>
<url><loc>https://behoerdenklar.de/ratgeber/behoerdenbrief-uebersetzen</loc><lastmod>2026-08-19</lastmod></url>
<url><loc>https://behoerdenklar.de/ratgeber/behoerdenpost-organisieren</loc><lastmod>2026-08-19</lastmod></url>
<url><loc>https://behoerdenklar.de/ratgeber/auf-behoerdenbrief-antworten</loc><lastmod>2026-08-19</lastmod></url>
</urlset>

132
webseite/widerruf.html Normal file
View File

@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Widerrufsbelehrung BehördenKlar</title>
<meta name="robots" content="noindex">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: #1a1a2e; background: #f4f8fb; line-height: 1.7;
}
.wrap { max-width: 640px; margin: 0 auto; padding: 32px 20px 64px; }
h1 { font-size: 28px; color: #144d8c; margin: 24px 0 4px; }
.stand { color: #4a5568; margin-bottom: 16px; }
h2 { font-size: 20px; color: #144d8c; margin: 24px 0 8px; }
p, li { margin-bottom: 8px; }
ul { padding-left: 24px; }
.karte {
background: #fff; border-radius: 16px; padding: 24px;
box-shadow: 0 2px 8px rgba(20, 77, 140, 0.08);
}
.kasten {
background: #f4f8fb; border: 1px solid #cfe0ef; border-radius: 12px;
padding: 16px 18px; margin-top: 12px;
}
a { color: #1a6bc4; }
.zurueck { display: inline-block; margin-top: 24px; }
</style>
</head>
<body>
<div class="wrap">
<h1>Widerrufsbelehrung</h1>
<p class="stand">für Verbraucher — Stand: 18.08.2026</p>
<div class="karte">
<h2>Widerrufsrecht</h2>
<p>
Sie haben das Recht, binnen vierzehn Tagen ohne Angabe von Gründen diesen
Vertrag zu widerrufen. Die Widerrufsfrist beträgt vierzehn Tage ab dem
Tag des Vertragsschlusses.
</p>
<p>
Um Ihr Widerrufsrecht auszuüben, müssen Sie uns
</p>
<div class="kasten">
Webklar GbR<br>
Justin Klein und Kenso Grimm<br>
Am Schwimmbad 10<br>
67722 Winnweiler<br>
E-Mail: <a href="mailto:behoerdenbriefhelfer@gmail.com">behoerdenbriefhelfer@gmail.com</a>
</div>
<p style="margin-top: 12px;">
mittels einer eindeutigen Erklärung (z. B. ein mit der Post versandter
Brief oder eine E-Mail) über Ihren Entschluss, diesen Vertrag zu
widerrufen, informieren. Sie können dafür das nachstehende
Muster-Widerrufsformular verwenden, das jedoch nicht vorgeschrieben ist.
</p>
<p>
Zur Wahrung der Widerrufsfrist reicht es aus, dass Sie die Mitteilung
über die Ausübung des Widerrufsrechts vor Ablauf der Widerrufsfrist
absenden.
</p>
<h2>Folgen des Widerrufs</h2>
<p>
Wenn Sie diesen Vertrag widerrufen, haben wir Ihnen alle Zahlungen, die
wir von Ihnen erhalten haben, unverzüglich und spätestens binnen
vierzehn Tagen ab dem Tag zurückzuzahlen, an dem die Mitteilung über
Ihren Widerruf dieses Vertrags bei uns eingegangen ist. Für diese
Rückzahlung verwenden wir dasselbe Zahlungsmittel, das Sie bei der
ursprünglichen Transaktion eingesetzt haben, es sei denn, mit Ihnen wurde
ausdrücklich etwas anderes vereinbart; in keinem Fall werden Ihnen wegen
dieser Rückzahlung Entgelte berechnet.
</p>
<h2>Vorzeitiges Erlöschen des Widerrufsrechts</h2>
<p>
Bei einem Vertrag über die Lieferung von nicht auf einem körperlichen
Datenträger befindlichen digitalen Inhalten erlischt das Widerrufsrecht
auch dann, wenn wir mit der Ausführung des Vertrags begonnen haben,
nachdem Sie
</p>
<ul>
<li>
ausdrücklich zugestimmt haben, dass wir mit der Ausführung des
Vertrags vor Ablauf der Widerrufsfrist beginnen, und
</li>
<li>
Ihre Kenntnis davon bestätigt haben, dass Sie durch Ihre Zustimmung
mit Beginn der Ausführung des Vertrags Ihr Widerrufsrecht verlieren.
</li>
</ul>
<p>
Diese Zustimmung und Bestätigung geben Sie über das Pflicht-Häkchen ab,
das Sie vor dem Kauf setzen. Sobald Ihr Guthaben bereitgestellt ist,
haben wir mit der Ausführung begonnen.
</p>
<h2>Muster-Widerrufsformular</h2>
<p>
(Wenn Sie den Vertrag widerrufen wollen, füllen Sie bitte dieses Formular
aus und senden Sie es zurück.)
</p>
<div class="kasten">
An:<br>
Webklar GbR, Am Schwimmbad 10, 67722 Winnweiler,
E-Mail: behoerdenbriefhelfer@gmail.com<br><br>
Hiermit widerrufe(n) ich/wir (*) den von mir/uns (*) abgeschlossenen
Vertrag über den Kauf des folgenden Guthabens (*):<br><br>
_______________________________________________<br><br>
Bestellt am (*) / erhalten am (*): ____________________<br>
Name des/der Verbraucher(s): ____________________<br>
Anschrift des/der Verbraucher(s): ____________________<br>
Datum: ____________________<br>
(Unterschrift nur bei Mitteilung auf Papier)<br><br>
(*) Unzutreffendes streichen.
</div>
</div>
<p style="margin-top: 20px; font-size: 15px;">
<a href="agb.html">AGB</a> ·
<a href="datenschutz.html">Datenschutzerklärung</a> ·
<a href="impressum.html">Impressum</a>
</p>
<a class="zurueck" href="index.html">← Zurück zur Startseite</a>
</div>
<!-- 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>