tools/anti-ai-lint.py: Python-Linter (stdlib + yq) prueft jede build/<domain>/index.html gegen die Blacklist in tools/anti-ai-blacklist.yaml. HTML wird via html.parser auf sichtbaren Text reduziert (Skripte/Styles werden ignoriert), dann werden Vokabel- Substrings (DE+EN, case-insensitive) und Regex-Patterns gematcht. Severity warn = Build geht durch, fail = Build bricht ab. Whitelist-Mechanismen: - HTML-Kommentar im Markup: <!-- anti-ai-allow: term1, term2 --> - Per-Site in site.yaml: anti_ai_allow: [term1, term2] Integration in build.sh als Schritt 4/4, mit --skip-lint fuer Notfaelle. Dockerfile installiert python3 zusaetzlich; nur im Builder-Stage, kein Effekt aufs Caddy-Image. Tests via tools/test-anti-ai-lint.sh: synthetische AI-Fixture wird korrekt geflagged, Whitelists unterdruecken Hits, fail-Severity triggert exit 1, neutraler Text exit 0. Initial-Lauf auf 59 bestehenden Sites: 2 warn (killusion.de "revolutionaer" in ironischem Kontext, kilofant.de "robust"), 0 fail. Cleanup ist Folge-Issue. README + docs/geo-seo-guideline.md aktualisiert mit der konkreten Tool-Position.
114 lines
2.8 KiB
Markdown
114 lines
2.8 KiB
Markdown
# onepager
|
|
|
|
Mono-repo for 40+ vanity domain onepager sites. Single nginx container with template system and server_name-based routing.
|
|
|
|
## Structure
|
|
|
|
```
|
|
sites/ # One folder per domain
|
|
example.de/
|
|
site.yaml # Domain config, template choice, variables
|
|
index.html # Content (generated or hand-crafted)
|
|
assets/ # Optional images, fonts
|
|
templates/ # Shared HTML templates
|
|
shared/css/ # Shared CSS (variables, responsive, animations)
|
|
nginx/ # Generated nginx.conf + generator script
|
|
build/ # Generated output (gitignored)
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Add a new site
|
|
|
|
```bash
|
|
# Templated site
|
|
./add-site.sh example.de --template person-dark --name "Max Mustermann"
|
|
|
|
# Custom HTML site
|
|
./add-site.sh example.de --template custom
|
|
```
|
|
|
|
### Build
|
|
|
|
```bash
|
|
./build.sh # build + anti-AI text lint
|
|
./build.sh --skip-lint # build only (emergencies)
|
|
```
|
|
|
|
Requires `yq` for YAML parsing and `python3` for the lint step. Outputs to `build/`.
|
|
|
|
### Anti-AI text lint
|
|
|
|
Every build runs `tools/anti-ai-lint.py` against `build/<domain>/index.html`,
|
|
flagging text fingerprints typical of LLM-generated content (vocab and structure
|
|
patterns from `tools/anti-ai-blacklist.yaml`). Severity `warn` prints a message;
|
|
`fail` aborts the build.
|
|
|
|
Whitelist a hit:
|
|
|
|
- HTML comment in the affected page:
|
|
`<!-- anti-ai-allow: revolutionär, em-dash-3-bullet -->`
|
|
- Per-site override in `site.yaml`:
|
|
```yaml
|
|
anti_ai_allow:
|
|
- revolutionär
|
|
- em-dash-3-bullet
|
|
```
|
|
|
|
The blacklist source is `docs/geo-seo-guideline.md` §3.6. Test the linter with
|
|
`tools/test-anti-ai-lint.sh`.
|
|
|
|
### Deploy
|
|
|
|
Push to main — Dokploy auto-deploys. All domains must be configured in Dokploy.
|
|
|
|
## Templates
|
|
|
|
| Template | Description |
|
|
|----------|-------------|
|
|
| `person-dark` | Professional profile, dark theme |
|
|
| `person-light` | Professional profile, light/cream theme |
|
|
| `product-dark` | Product/service landing page, dark |
|
|
| `editorial` | Long-form manifesto/editorial style |
|
|
| `fun` | Playful/personal pages |
|
|
| `minimal` | Bare-bones single section |
|
|
| `custom` | Hand-crafted HTML, no rendering |
|
|
|
|
## site.yaml
|
|
|
|
```yaml
|
|
domain: example.de
|
|
aliases: [www.example.de]
|
|
template: person-dark
|
|
title: "Page Title"
|
|
description: "Meta description"
|
|
lang: de
|
|
|
|
vars:
|
|
name: "Name"
|
|
role: "Role"
|
|
initials: "AB"
|
|
tagline: "Tagline here"
|
|
accent: "#c9a84c"
|
|
accent_light: "rgba(201, 168, 76, 0.1)"
|
|
font_primary: "Inter"
|
|
font_secondary: "Newsreader"
|
|
tags: ["Tag 1", "Tag 2"]
|
|
sections:
|
|
- type: features
|
|
title: "Section Title"
|
|
items:
|
|
- title: "Item"
|
|
desc: "Description"
|
|
- type: profile
|
|
bio: "Bio text"
|
|
cta:
|
|
text: "Contact"
|
|
href: "mailto:info@example.de"
|
|
```
|
|
|
|
## Related
|
|
|
|
- Issue #341: Onepager Mono-Repo
|
|
- Issue #335: Container consolidation
|