Impressum and Datenschutz, in both languages — and stop logging IPs
Four pages: /imprint/ and /privacy/ in English, /de/impressum/ and /de/datenschutz/ in German, linked from the footer of the matching language. The German version is the authoritative one; the English one says so. Every fact in them was checked rather than assumed. The hosting section comes from the Art. 28 processing agreement with Hetzner (EU/EEA only, DPO appointed, breach notification, ISO 27001, BSI C5 Type 2); the server location comes from the provider's API and is Nuremberg; the "no cookies, no third-party requests, nothing in your browser" claim comes from loading the live page in a browser that records every outgoing request — all of them went to this domain, with zero cookies and an empty localStorage. nginx now logs without the client address. The default format was writing $remote_addr and X-Forwarded-For, so a static page that needs no personal data at all was storing the IP of everyone who looked at it. The log keeps time, request, status, size, referrer and user agent — enough to operate the site, minus the field that identifies a person. Data minimisation beats a retention policy you then have to honour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nh4A79bbqT9dcd2inzYUdg
This commit is contained in:
10 files changed
+299
-3
No files matched your search
@@ -0,0 +1,77 @@
|
||||
---
|
||||
import '@fontsource/space-grotesk/400.css';
|
||||
import '@fontsource/space-grotesk/500.css';
|
||||
import '@fontsource/space-grotesk/700.css';
|
||||
import '@fontsource/space-mono/400.css';
|
||||
import '@fontsource/space-mono/700.css';
|
||||
import '../styles/tokens.css';
|
||||
import '../styles/site.css';
|
||||
import type { LegalPage } from '../lib/legal';
|
||||
|
||||
interface Props {
|
||||
page: LegalPage;
|
||||
lang: 'en' | 'de';
|
||||
canonical: string;
|
||||
otherHref: string;
|
||||
otherLabel: string;
|
||||
backHref: string;
|
||||
backLabel: string;
|
||||
siblingHref: string;
|
||||
siblingLabel: string;
|
||||
}
|
||||
const { page, lang, canonical, otherHref, otherLabel, backHref, backLabel, siblingHref, siblingLabel } = Astro.props;
|
||||
const home = lang === 'de' ? '/de/' : '/';
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang={lang}>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<meta name="theme-color" content="#EAEAE3" />
|
||||
<title>{page.title} · Klarbild</title>
|
||||
<meta name="robots" content="noindex, follow" />
|
||||
<link rel="canonical" href={canonical} />
|
||||
</head>
|
||||
<body>
|
||||
<header class="top">
|
||||
<div class="shell top-in">
|
||||
<a class="brand" href={home}><span class="regmark"></span>klarbild</a>
|
||||
<nav>
|
||||
<a href={backHref}>{backLabel}</a>
|
||||
<a class="langswitch" href={otherHref} hreflang={otherLabel.toLowerCase()}>{otherLabel}</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="legal shell">
|
||||
<span class="kicker">{page.updated}</span>
|
||||
<h1>{page.title}</h1>
|
||||
{page.intro && <p class="lead">{page.intro}</p>}
|
||||
|
||||
{page.blocks.map((b) => (
|
||||
<section class="lblock">
|
||||
{b.h && <h2>{b.h}</h2>}
|
||||
{b.rows && (
|
||||
<dl class="lrows">
|
||||
{b.rows.map(([k, v]) => (<><dt>{k}</dt><dd>{v}</dd></>))}
|
||||
</dl>
|
||||
)}
|
||||
{b.p && <p>{b.p}</p>}
|
||||
{b.html && <p set:html={b.html} />}
|
||||
</section>
|
||||
))}
|
||||
|
||||
<p class="lsibling"><a href={siblingHref}>{siblingLabel}</a></p>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="shell foot-in">
|
||||
<a class="brand" href={home}><span class="regmark"></span>klarbild</a>
|
||||
<a href={backHref}>{backLabel}</a>
|
||||
<a href={siblingHref}>{siblingLabel}</a>
|
||||
<a href="https://github.com/tillheidrich/klarbild" rel="noopener">GitHub</a>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user