Generate legally required pages (Impressum, Datenschutzerklärung, Cookie-Hinweis, or the EU equivalents) for a cogni-website project based on the publishing jurisdiction (DE, AT, CH, EU). Captures the legal entity facts, fills jurisdiction-specific boilerplate templates, writes the markdown source files, and patches website-plan.json so the existing build pipeline renders them. Use this skill whenever the user mentions "Impressum", "Datenschutz", "Datenschutzerklärung", "Cookie-Hinweis", "DSG...
Scanned 9/12/2026
Install to Claude Code
npx -y skills add aibot88/sec_skill_store --skill website-legal --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Website Legal?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-website-legal)More formats (shields.io, HTML) on the badges page.
---
name: website-legal
description: |
Generate legally required pages (Impressum, Datenschutzerklärung, Cookie-Hinweis, or the EU
equivalents) for a cogni-website project based on the publishing jurisdiction (DE, AT, CH, EU).
Captures the legal entity facts, fills jurisdiction-specific boilerplate templates, writes the
markdown source files, and patches website-plan.json so the existing build pipeline renders them.
Use this skill whenever the user mentions "Impressum", "Datenschutz", "Datenschutzerklärung",
"Cookie-Hinweis", "DSGVO", "GDPR", "Pflichtangaben", "rechtliche Seiten", "legal pages", "legal
notice", "privacy policy", "compliance pages", "TMG", "ECG", "revDSG", "Rechtstexte erzeugen",
or wants to add legally required content for Germany, Austria, Switzerland, or the EU — even if
they don't say "skill" or name a specific page. Requires website-project.json (from website-setup).
allowed-tools: Read, Write, Edit, Glob, Bash, AskUserQuestion
---
# Website Legal
Generate jurisdiction-specific legal pages from reviewable boilerplate templates. The skill never invents legal text — all wording comes from the template bundles in `references/jurisdictions/`. Claude only fills `{{placeholders}}` with facts captured from the user.
## Disclaimer
The generated pages are templates, not legal advice. Always print the disclaimer in the final summary: **"Diese Texte sind Vorlagen. Vor der Veröffentlichung durch eine Anwältin oder einen Anwalt prüfen lassen."** Adapt the disclaimer to project language.
## Prerequisites
A `website-project.json` must exist in the working directory. If missing, redirect to `website-setup`. A `website-plan.json` is **not** required — `website-legal` can run before or after `website-plan`. If the plan does not yet exist, the skill writes the legal page entries to a queue file (`legal-pages.json`) that `website-plan` will pick up.
## Workflow
### 1. Load Project
Read `website-project.json`. Extract:
- `language` (drives all user-facing prompts and template language; default `de`)
- `company` (name, tagline, contact)
- `legal_config` (may be missing, partial, or complete)
If `legal_config` is missing, create an empty object.
### 2. Determine Jurisdiction
If `legal_config.jurisdiction` is not set, ask the user via `AskUserQuestion`:
> "In welcher Rechtsordnung wird die Website veröffentlicht?"
Options:
- **Deutschland (DE)** — TMG §5, DSGVO, Telemediengesetz
- **Österreich (AT)** — ECG §5, DSG, DSGVO
- **Schweiz (CH)** — revDSG, freiwillige Anbieterkennzeichnung
- **EU (übrige Mitgliedstaaten)** — DSGVO, ePrivacy, generischer Legal Notice
Persist the choice to `legal_config.jurisdiction`.
### 3. Capture Legal Entity Facts
Read `references/legal-config-schema.md` to learn the full field set, then check which fields are still missing for the chosen jurisdiction (see the requirement matrix in that file).
Ask only for missing fields. Adapt the questions to project language. Group questions logically — capture the legal entity in one round, then the responsible person, then VAT/registration in a third round so the user is not overwhelmed.
Required-by-jurisdiction matrix (high level — see `references/legal-config-schema.md` for exact rules):
| Field | DE | AT | CH | EU |
|-------|----|----|----|----|
| `legal_entity.legal_name` | required | required | required | required |
| `legal_entity.legal_form` | required | required | recommended | recommended |
| `legal_entity.address` | required | required | required | required |
| `legal_entity.register_court` | required (if HRB) | — | — | optional |
| `legal_entity.register_number` | required (if HRB) | required (FN) | optional (CHE) | optional |
| `legal_entity.vat_id` | required (if applicable) | required (if applicable) | optional | required (if applicable) |
| `responsible_person.name` | required (§55 RStV) | required (§24 MedienG) | recommended | recommended |
| `responsible_person.address` | required if differs from legal_entity | required if differs | optional | optional |
| `supervisory_authority` | required (if regulated) | required (if regulated) | optional | optional |
| `professional_regulations` | required (if regulated profession) | required (if regulated) | optional | optional |
| `dispute_resolution.os_platform_link` | required (EU consumer business) | required (EU consumer business) | — | required (EU consumer) |
| `contact.email` | required | required | required | required |
| `contact.phone` | required | required | recommended | recommended |
| `data_protection.controller_name` | required (DSGVO Art. 13) | required | required (revDSG) | required |
| `data_protection.dpo_contact` | required if DPO mandatory | required if DPO mandatory | optional | required if DPO mandatory |
Persist captured fields immediately to `website-project.json` → `legal_config` after each round, so a long capture session is never lost.
### 4. Validate Required Fields
Before generating templates, run a completeness check against the matrix. If required fields for the chosen jurisdiction are still missing, list them and ask the user one more time. If the user explicitly says "use placeholder for now", insert a literal `«TODO: <field>»` marker — never invent values.
### 5. Select Template Bundle
Pick the bundle directory from `${CLAUDE_PLUGIN_ROOT}/skills/website-legal/references/jurisdictions/`:
| Jurisdiction | Bundle path | Page slugs |
|--------------|-------------|------------|
| `de` | `references/jurisdictions/de/` | `impressum`, `datenschutz`, `cookies` |
| `at` | `references/jurisdictions/at/` | `impressum`, `datenschutz`, `cookies` |
| `ch` | `references/jurisdictions/ch/` | `impressum`, `datenschutz`, `cookies` |
| `eu` | `references/jurisdictions/eu/` | `legal-notice`, `privacy-policy`, `cookies` |
Each bundle contains three files: an imprint/legal-notice template, a privacy template, and a cookies template, all with the `.md.tmpl` extension.
### 6. Render Templates
For each template file in the bundle:
1. Read the template content with the `Read` tool.
2. Substitute every `{{placeholder}}` token with the corresponding value from `legal_config`, `company`, or the current date. Supported placeholder paths are documented in `references/placeholder-schema.md`.
3. If a placeholder has no value, insert the literal string `«TODO: <placeholder>»` so the gap is visible in the rendered HTML.
4. Replace `{{generated_at}}` with the current date in ISO format and `{{generated_at_human}}` with the localized form (e.g. "8. April 2026" for `de`).
5. Write the result to `content/legal/{slug}.md` in the project directory. Create the `content/legal/` directory if it does not exist.
The output is markdown, not HTML. The existing `page-generator` agent renders these markdown files to HTML during `website-build` using the legal page templates from `${CLAUDE_PLUGIN_ROOT}/libraries/legal-pages.md`.
### 7. Patch website-plan.json (if it exists)
If `website-plan.json` exists in the project directory:
1. Read it.
2. Remove any existing legal page entries (page IDs starting with `legal-`) so re-runs are idempotent.
3. Append three new page entries — one per generated legal page — using the structure from `${CLAUDE_PLUGIN_ROOT}/libraries/EXAMPLE_WEBSITE_PLAN.md` (legal section). Each entry has:
- `id`: `legal-imprint`, `legal-privacy`, `legal-cookies`
- `type`: `legal-imprint` | `legal-privacy` | `legal-cookies`
- `slug`: `pages/impressum` | `pages/datenschutz` | `pages/cookies` (or `legal-notice`/`privacy-policy` for EU)
- `title`: localized page title — site title
- `meta_description`: short SEO description (e.g. "Impressum gemäß § 5 TMG")
- `source_files`: `["content/legal/{slug}.md"]`
- `sections`: `["legal-header", "legal-body"]`
- `footer_only`: `true` — exclude from primary nav, include in footer legal column
4. Add or replace the top-level `legal_links` array. Labels and slugs come from the jurisdiction bundle and the project `language` — never hardcode German. The DE example below is illustrative only; for `eu` the slugs become `legal-notice` / `privacy-policy` and the labels are English:
```json
[
{ "label": "Impressum", "href": "/pages/impressum.html" },
{ "label": "Datenschutz", "href": "/pages/datenschutz.html" },
{ "label": "Cookies", "href": "/pages/cookies.html" }
]
```
5. Write the updated plan back atomically.
If `website-plan.json` does **not** yet exist, write the entries and the `legal_links` array to `legal-pages.json` in the project directory. The `website-plan` skill will merge `legal-pages.json` into the plan it generates (see the page-type-registry for details).
### 8. Print Summary
Render the summary in the project `language`. The German example below is the shape, not a literal template — translate the labels when `language` differs.
```
Rechtliche Seiten erstellt für Rechtsordnung: {jurisdiction_name}
Generierte Seiten:
✓ content/legal/impressum.md ({n} Wörter)
✓ content/legal/datenschutz.md ({n} Wörter)
✓ content/legal/cookies.md ({n} Wörter)
Konfiguration:
Rechtsträger: {legal_entity.legal_name}
Anschrift: {legal_entity.address.city}
Verantwortlich: {responsible_person.name}
USt-IdNr.: {legal_entity.vat_id}
Offene Platzhalter: {n} ← bitte vor Veröffentlichung füllen
Plan aktualisiert: ja|nein (legal-pages.json zwischengespeichert)
⚠ Diese Texte sind Vorlagen. Vor der Veröffentlichung durch eine Anwältin oder
einen Anwalt prüfen lassen.
Nächster Schritt: /website-build — Seiten generieren (oder /website-plan, falls
noch nicht ausgeführt).
```
If any `«TODO: ...»` placeholders are still present, list them explicitly so the user can fix them before building.
## Re-running the Skill
The skill is idempotent. Re-running it:
- Re-reads `legal_config` from `website-project.json`
- Asks only for fields that are still missing
- Overwrites `content/legal/*.md` with freshly rendered templates
- Replaces existing `legal-*` page entries in `website-plan.json` (no duplication)
If the user wants to switch jurisdictions, ask them to confirm — switching deletes the old templates and writes new ones. Old captured facts in `legal_config` are preserved where the new jurisdiction needs the same fields.
## Output Language
All user-facing text and template output use the project `language` field. Default `de`. Each jurisdiction bundle currently ships with German templates (DE/AT/CH) and an English template (EU). When the project language differs from the bundle language, render the templates as-is and warn the user.
## Reference Files
- `${CLAUDE_PLUGIN_ROOT}/skills/website-legal/references/legal-config-schema.md` — full schema and per-jurisdiction requirement rules
- `${CLAUDE_PLUGIN_ROOT}/skills/website-legal/references/placeholder-schema.md` — list of supported `{{placeholders}}` and their source paths
- `${CLAUDE_PLUGIN_ROOT}/skills/website-legal/references/jurisdictions/{de,at,ch,eu}/` — boilerplate templates
- `${CLAUDE_PLUGIN_ROOT}/libraries/legal-pages.md` — HTML/CSS pattern for legal page rendering
- `${CLAUDE_PLUGIN_ROOT}/libraries/EXAMPLE_WEBSITE_PLAN.md` — reference for the legal page entries and `legal_links` array
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!