feat: initial Hugo blog for internetforkids.ong

Child safety marketing blog with:
- First article: Global Child Protection Laws 2026 (EN/DE)
- Interactive world map (17 countries, TopoJSON)
- SEO: JSON-LD, OpenGraph, hreflang, canonical URLs
- AI search: robots.txt, llms.txt, FAQ sections
- VPN CTA shortcode, about pages, tag taxonomy
- Rybbit analytics partial (site ID TBD)
- Dockerfile + nginx.conf for deployment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-04-02 06:58:49 +03:00
commit bdd2da36d5
24 changed files with 971 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
{{/* Structured data for SEO + AI search */}}
{{ partial "structured-data.html" . }}
{{/* Hreflang tags for multilingual SEO */}}
{{ if .IsTranslated }}
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />
{{ range .Translations }}
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />
{{ end }}
{{ end }}
{{/* Canonical URL */}}
<link rel="canonical" href="{{ .Permalink }}" />
{{/* AI Search Engine Optimization */}}
{{/* Allow all AI crawlers — maximize discoverability */}}
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large" />
{{/* Explicit AI crawler permissions */}}
<meta name="googlebot" content="index, follow" />
{{/* Clear, machine-parseable description for AI summarization */}}
{{ if .IsPage }}
<meta name="topic" content="{{ .Title }}" />
<meta name="subject" content="{{ .Description | default .Summary | plainify | truncate 160 }}" />
{{ with .Params.tags }}<meta name="keywords" content="{{ delimit . ", " }}" />{{ end }}
<meta name="article:published_time" content="{{ .Date.Format "2006-01-02" }}" />
<meta name="article:modified_time" content="{{ .Lastmod.Format "2006-01-02" }}" />
<meta name="article:section" content="{{ .Section }}" />
<meta name="article:author" content="{{ .Params.author | default "Agiliton" }}" />
{{ end }}
{{/* LLMs.txt discovery */}}
<link rel="alternate" type="text/plain" href="/llms.txt" title="LLM-readable site description" />

View File

@@ -0,0 +1,2 @@
{{/* Rybbit privacy-friendly analytics */}}
{{ partial "rybbit.html" . }}

View File

@@ -0,0 +1,9 @@
{{ if .IsTranslated }}
<nav class="language-switcher" aria-label="Language">
{{ range .Translations }}
<a href="{{ .Permalink }}" lang="{{ .Language.Lang }}" hreflang="{{ .Language.Lang }}">
{{ .Language.LanguageName }}
</a>
{{ end }}
</nav>
{{ end }}

View File

@@ -0,0 +1,3 @@
{{ with site.Params.rybbit_site_id }}
<script src="{{ site.Params.rybbit_url }}/script.js" data-site-id="{{ . }}" defer></script>
{{ end }}

View File

@@ -0,0 +1,73 @@
{{ if .IsPage }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "{{ .Title }}",
"description": "{{ .Description | default (.Summary | plainify) }}",
"datePublished": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
"dateModified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}",
"author": {
"@type": "Organization",
"name": "Agiliton",
"url": "https://www.agiliton.eu"
},
"publisher": {
"@type": "Organization",
"name": "Agiliton",
"url": "https://www.agiliton.eu"
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{{ .Permalink }}"
},
"inLanguage": "{{ .Language.Lang }}",
"wordCount": {{ .WordCount }}
{{ with .Params.tags }},
"keywords": {{ . | jsonify }}
{{ end }}
}
</script>
{{/* BreadcrumbList for AI search navigation */}}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "{{ site.Title }}",
"item": "{{ site.BaseURL }}"
},
{
"@type": "ListItem",
"position": 2,
"name": "{{ .Section | title }}",
"item": "{{ printf "%s%s/" site.BaseURL .Section }}"
},
{
"@type": "ListItem",
"position": 3,
"name": "{{ .Title }}",
"item": "{{ .Permalink }}"
}
]
}
</script>
{{ else }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "{{ site.Title }}",
"url": "{{ site.BaseURL }}",
"description": "{{ site.Params.description }}",
"publisher": {
"@type": "Organization",
"name": "Agiliton",
"url": "https://www.agiliton.eu"
}
}
</script>
{{ end }}

View File

@@ -0,0 +1,13 @@
<aside class="vpn-cta" style="background: linear-gradient(135deg, #1a365d 0%, #2d5ca8 100%); color: #fff; padding: 2rem; border-radius: 12px; margin: 2rem 0; text-align: center;">
<h3 style="margin: 0 0 0.75rem; font-size: 1.25rem;">{{ if eq .Language.Lang "de" }}Schützen Sie Ihre Familie online{{ else }}Protect Your Family Online{{ end }}</h3>
<p style="margin: 0 0 1.25rem; opacity: 0.9; font-size: 0.95rem;">
{{ if eq .Language.Lang "de" }}
Agiliton VPN bietet Inhaltsfilterung, Geräteschutz und sicheres Surfen für die ganze Familie.
{{ else }}
Agiliton VPN provides content filtering, device protection, and safe browsing for the whole family.
{{ end }}
</p>
<a href="https://www.agiliton.eu/vpn" style="display: inline-block; background: #fff; color: #1a365d; padding: 0.75rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
{{ if eq .Language.Lang "de" }}Mehr erfahren{{ else }}Learn More{{ end }}
</a>
</aside>

29
layouts/robots.txt Normal file
View File

@@ -0,0 +1,29 @@
User-agent: *
Allow: /
# Explicitly allow AI search crawlers
User-agent: GPTBot
Allow: /
User-agent: ChatGPT-User
Allow: /
User-agent: Google-Extended
Allow: /
User-agent: anthropic-ai
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: CCBot
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: Bytespider
Allow: /
Sitemap: {{ "sitemap.xml" | absURL }}

View File

@@ -0,0 +1,303 @@
<style>
.csm-container {
max-width: 100%;
margin: 2rem 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.csm-container h3 {
text-align: center;
margin-bottom: 0.5rem;
font-size: 1.25rem;
}
.csm-subtitle {
text-align: center;
color: #666;
font-size: 0.85rem;
margin-bottom: 1rem;
}
.csm-map-wrapper {
position: relative;
background: #f8fafc;
border-radius: 12px;
padding: 1rem;
border: 1px solid #e2e8f0;
}
.csm-map-wrapper svg {
width: 100%;
height: auto;
}
.csm-map-wrapper path.country {
stroke: #fff;
stroke-width: 0.5;
cursor: pointer;
transition: opacity 0.2s;
}
.csm-map-wrapper path.country:hover {
opacity: 0.8;
stroke-width: 1.5;
stroke: #1a365d;
}
.csm-tooltip {
display: none;
position: absolute;
background: #1a365d;
color: #fff;
padding: 0.75rem 1rem;
border-radius: 8px;
font-size: 0.85rem;
max-width: 280px;
z-index: 10;
pointer-events: none;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.csm-tooltip .csm-tt-title {
font-weight: 700;
margin-bottom: 0.25rem;
}
.csm-tooltip .csm-tt-status {
font-size: 0.8rem;
opacity: 0.9;
}
.csm-legend {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
margin-top: 1rem;
font-size: 0.8rem;
}
.csm-legend-item {
display: flex;
align-items: center;
gap: 0.35rem;
}
.csm-legend-swatch {
width: 14px;
height: 14px;
border-radius: 3px;
border: 1px solid rgba(0,0,0,0.1);
}
</style>
<div class="csm-container">
<h3>{{ if eq .Page.Language.Lang "de" }}Kinderschutzgesetze weltweit{{ else }}Child Protection Laws Worldwide{{ end }}</h3>
<p class="csm-subtitle">{{ if eq .Page.Language.Lang "de" }}Klicken Sie auf ein Land für Details{{ else }}Click a country for details{{ end }}</p>
<div class="csm-map-wrapper" id="csm-map">
<div class="csm-tooltip" id="csm-tooltip">
<div class="csm-tt-title" id="csm-tt-title"></div>
<div class="csm-tt-status" id="csm-tt-status"></div>
</div>
</div>
<div class="csm-legend">
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#1e40af"></div>{{ if eq .Page.Language.Lang "de" }}Gesetz in Kraft{{ else }}Law Enforced{{ end }}</div>
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#3b82f6"></div>{{ if eq .Page.Language.Lang "de" }}Gesetzgebung verabschiedet{{ else }}Legislation Passed{{ end }}</div>
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#93c5fd"></div>{{ if eq .Page.Language.Lang "de" }}In Bearbeitung{{ else }}In Progress{{ end }}</div>
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#dbeafe"></div>{{ if eq .Page.Language.Lang "de" }}Richtlinien / Selbstregulierung{{ else }}Guidelines / Self-Regulation{{ end }}</div>
<div class="csm-legend-item"><div class="csm-legend-swatch" style="background:#e2e8f0"></div>{{ if eq .Page.Language.Lang "de" }}Keine spezifische Gesetzgebung{{ else }}No Specific Legislation{{ end }}</div>
</div>
</div>
<script>
(function() {
var lang = {{ .Page.Language.Lang | jsonify }};
// Country data: status, law name, details
var data = {
"AU": {
status: "enforced",
en: { name: "Australia", law: "Social Media Minimum Age Act 2024", detail: "Social media ban for under-16s. Enforced Dec 2025. Fines up to AUD 49.5M." },
de: { name: "Australien", law: "Social Media Minimum Age Act 2024", detail: "Social-Media-Verbot für unter 16-Jährige. In Kraft seit Dez. 2025. Bußgelder bis 49,5 Mio. AUD." }
},
"US": {
status: "in_progress",
en: { name: "United States", law: "KOSA + COPPA Update", detail: "KOSA passed Senate 91-3, in House committee. COPPA update requires compliance by Apr 2026." },
de: { name: "Vereinigte Staaten", law: "KOSA + COPPA-Update", detail: "KOSA im Senat mit 91-3 angenommen, im Ausschuss des Repräsentantenhauses. COPPA-Update erfordert Konformität bis Apr. 2026." }
},
"GB": {
status: "enforced",
en: { name: "United Kingdom", law: "Online Safety Act 2023 + Age Appropriate Design Code", detail: "Comprehensive online safety regime. Age verification required. Ofcom enforcement active." },
de: { name: "Vereinigtes Königreich", law: "Online Safety Act 2023 + Age Appropriate Design Code", detail: "Umfassendes Online-Sicherheitsregime. Altersverifikation erforderlich. Ofcom-Durchsetzung aktiv." }
},
"DE": {
status: "enforced",
en: { name: "Germany", law: "Jugendschutzgesetz (JuSchG)", detail: "Youth Protection Act extended to online platforms. BzKJ actively monitoring compliance." },
de: { name: "Deutschland", law: "Jugendschutzgesetz (JuSchG)", detail: "Jugendschutzgesetz auf Online-Plattformen ausgeweitet. BzKJ überwacht aktiv die Einhaltung." }
},
"FR": {
status: "passed",
en: { name: "France", law: "Digital Majority Act (Loi SREN)", detail: "Age verification mandate for adult content. Social media age 15 with parental consent." },
de: { name: "Frankreich", law: "Loi SREN (Digitale Volljährigkeit)", detail: "Altersverifikation für Erwachseneninhalte. Social Media ab 15 mit elterlicher Zustimmung." }
},
"IE": {
status: "enforced",
en: { name: "Ireland", law: "Online Safety and Media Regulation Act", detail: "Coimisiún na Meán regulates online safety. Binding online safety codes for platforms." },
de: { name: "Irland", law: "Online Safety and Media Regulation Act", detail: "Coimisiún na Meán reguliert Online-Sicherheit. Verbindliche Kodizes für Plattformen." }
},
"BR": {
status: "passed",
en: { name: "Brazil", law: "ECA Digital (Digital Child Statute)", detail: "Loot box ban for minors. Age-appropriate design requirements. Enhanced child data protection." },
de: { name: "Brasilien", law: "ECA Digital", detail: "Lootbox-Verbot für Minderjährige. Altersgerechtes Design. Verstärkter Datenschutz für Kinder." }
},
"IN": {
status: "passed",
en: { name: "India", law: "DPDP Act 2023", detail: "Digital Personal Data Protection Act. Verifiable parental consent for under-18s." },
de: { name: "Indien", law: "DPDP Act 2023", detail: "Gesetz zum Schutz personenbezogener Daten. Verifizierbare elterliche Einwilligung für unter 18-Jährige." }
},
"KR": {
status: "enforced",
en: { name: "South Korea", law: "Youth Protection Act + Game Shutdown Law", detail: "Long-standing youth protection framework. Real-name verification for online services." },
de: { name: "Südkorea", law: "Jugendschutzgesetz + Game Shutdown Law", detail: "Langjähriger Jugendschutzrahmen. Echtnamen-Verifizierung für Online-Dienste." }
},
"JP": {
status: "guidelines",
en: { name: "Japan", law: "Act on Regulation of Soliciting Children", detail: "Platform self-regulation encouraged. Industry guidelines for age-appropriate services." },
de: { name: "Japan", law: "Gesetz zur Regulierung der Kontaktaufnahme mit Kindern", detail: "Selbstregulierung der Plattformen empfohlen. Branchenrichtlinien für altersgerechte Dienste." }
},
"CN": {
status: "enforced",
en: { name: "China", law: "Minor Protection Law + Gaming Restrictions", detail: "Strict limits: 1hr/day gaming for minors. Real-name verification. Content filtering mandatory." },
de: { name: "China", law: "Minderjährigenschutzgesetz + Gaming-Beschränkungen", detail: "Strenge Grenzen: 1 Std./Tag Gaming für Minderjährige. Echtnamen-Verifizierung. Inhaltsfilterung verpflichtend." }
},
"CA": {
status: "in_progress",
en: { name: "Canada", law: "Online Harms Act (Bill C-63)", detail: "Proposed duty of care for platforms. Age verification requirements under consideration." },
de: { name: "Kanada", law: "Online Harms Act (Bill C-63)", detail: "Vorgeschlagene Sorgfaltspflicht für Plattformen. Altersverifikation in Prüfung." }
},
"NL": {
status: "enforced",
en: { name: "Netherlands", law: "DSA + Children's Code (AP)", detail: "Dutch DPA actively enforcing children's data protection. TikTok fined EUR 750K." },
de: { name: "Niederlande", law: "DSA + Kinderkodex (AP)", detail: "Niederländische Datenschutzbehörde setzt Kinderdatenschutz aktiv durch. TikTok mit 750.000 EUR bestraft." }
},
"IT": {
status: "passed",
en: { name: "Italy", law: "DSA + Parental Consent Law", detail: "Digital age of consent set to 14. Garante actively enforcing children's privacy rights." },
de: { name: "Italien", law: "DSA + Einwilligungsgesetz", detail: "Digitales Einwilligungsalter auf 14 festgelegt. Garante setzt Kinderdatenschutz aktiv durch." }
},
"ES": {
status: "passed",
en: { name: "Spain", law: "Organic Law on Child Protection in Digital Environments", detail: "Comprehensive child digital protection law. Age verification and content moderation required." },
de: { name: "Spanien", law: "Organisches Gesetz zum Kinderschutz in digitalen Umgebungen", detail: "Umfassendes digitales Kinderschutzgesetz. Altersverifikation und Inhaltsmoderation erforderlich." }
},
"SE": {
status: "enforced",
en: { name: "Sweden", law: "DSA + National Board for Youth Affairs", detail: "EU DSA framework plus national youth protection guidelines. Active enforcement." },
de: { name: "Schweden", law: "DSA + Nationale Jugendbehörde", detail: "EU-DSA-Rahmen plus nationale Jugendschutzrichtlinien. Aktive Durchsetzung." }
},
"NO": {
status: "passed",
en: { name: "Norway", law: "Social Media Age Limit (proposed 15)", detail: "Proposed social media age limit of 15. Following Australia's model." },
de: { name: "Norwegen", law: "Social-Media-Altersgrenze (geplant: 15)", detail: "Geplante Social-Media-Altersgrenze von 15 Jahren. Folgt Australiens Modell." }
}
};
var colors = {
enforced: "#1e40af",
passed: "#3b82f6",
in_progress: "#93c5fd",
guidelines: "#dbeafe",
none: "#e2e8f0"
};
// Fetch a lightweight world TopoJSON and render via inline SVG
// Using Natural Earth 110m simplified for fast loading
var mapEl = document.getElementById("csm-map");
var tooltip = document.getElementById("csm-tooltip");
var ttTitle = document.getElementById("csm-tt-title");
var ttStatus = document.getElementById("csm-tt-status");
// Load world GeoJSON (tiny, ~50KB)
fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json")
.then(function(r) { return r.json(); })
.then(function(topo) {
// We need topojson-client to convert
var script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js";
script.onload = function() {
renderMap(topo);
};
document.head.appendChild(script);
})
.catch(function() {
mapEl.innerHTML += '<p style="text-align:center;color:#999;padding:2rem;">Map could not be loaded. Please check your internet connection.</p>';
});
// ISO 3166-1 numeric to alpha-2 mapping (key countries)
var numToAlpha = {
"36":"AU","76":"BR","124":"CA","156":"CN","250":"FR","276":"DE","356":"IN",
"372":"IE","380":"IT","392":"JP","410":"KR","528":"NL","578":"NO","724":"ES",
"752":"SE","826":"GB","840":"US"
};
function renderMap(topo) {
var countries = topojson.feature(topo, topo.objects.countries);
// Simple equirectangular projection
var w = 960, h = 480;
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 " + w + " " + h);
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
countries.features.forEach(function(f) {
var id = f.id;
var alpha2 = numToAlpha[id] || "";
var info = data[alpha2];
var color = info ? colors[info.status] : colors.none;
var paths = geoToPath(f.geometry, w, h);
paths.forEach(function(d) {
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("d", d);
path.setAttribute("fill", color);
path.setAttribute("class", "country");
path.setAttribute("data-id", alpha2);
if (info) {
path.addEventListener("mouseenter", function(e) {
var loc = info[lang] || info.en;
ttTitle.textContent = loc.name + " — " + loc.law;
ttStatus.textContent = loc.detail;
tooltip.style.display = "block";
});
path.addEventListener("mousemove", function(e) {
var rect = mapEl.getBoundingClientRect();
var x = e.clientX - rect.left + 10;
var y = e.clientY - rect.top - 10;
if (x + 280 > rect.width) x = x - 300;
tooltip.style.left = x + "px";
tooltip.style.top = y + "px";
});
path.addEventListener("mouseleave", function() {
tooltip.style.display = "none";
});
}
svg.appendChild(path);
});
});
mapEl.insertBefore(svg, tooltip);
}
// Minimal equirectangular geo→SVG path converter
function geoToPath(geom, w, h) {
var paths = [];
var coords = [];
if (geom.type === "Polygon") coords = [geom.coordinates];
else if (geom.type === "MultiPolygon") coords = geom.coordinates;
coords.forEach(function(poly) {
poly.forEach(function(ring) {
var d = "";
ring.forEach(function(pt, i) {
var x = (pt[0] + 180) / 360 * w;
var y = (90 - pt[1]) / 180 * h;
d += (i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1);
});
d += "Z";
paths.push(d);
});
});
return paths;
}
})();
</script>

View File

@@ -0,0 +1,13 @@
{{/* FAQ shortcode — renders as expandable details + outputs FAQPage schema for AI search */}}
{{ $items := .Inner | split "---" }}
<div class="faq-section">
{{ range $items }}
{{ $parts := . | split "?" }}
{{ if gt (len $parts) 1 }}
<details class="faq-item" style="margin-bottom: 0.75rem; border: 1px solid #e2e8f0; border-radius: 8px; padding: 0;">
<summary style="padding: 0.75rem 1rem; cursor: pointer; font-weight: 600; list-style: none;">{{ index $parts 0 | markdownify }}?</summary>
<div style="padding: 0 1rem 0.75rem; color: #4a5568;">{{ index $parts 1 | markdownify }}</div>
</details>
{{ end }}
{{ end }}
</div>

View File

@@ -0,0 +1,13 @@
<aside class="vpn-cta" style="background: linear-gradient(135deg, #1a365d 0%, #2d5ca8 100%); color: #fff; padding: 2rem; border-radius: 12px; margin: 2rem 0; text-align: center;">
<h3 style="margin: 0 0 0.75rem; font-size: 1.25rem;">{{ if eq .Page.Language.Lang "de" }}Schützen Sie Ihre Familie online{{ else }}Protect Your Family Online{{ end }}</h3>
<p style="margin: 0 0 1.25rem; opacity: 0.9; font-size: 0.95rem;">
{{ if eq .Page.Language.Lang "de" }}
Agiliton VPN bietet Inhaltsfilterung, Geräteschutz und sicheres Surfen für die ganze Familie.
{{ else }}
Agiliton VPN provides content filtering, device protection, and safe browsing for the whole family.
{{ end }}
</p>
<a href="https://www.agiliton.eu/vpn" style="display: inline-block; background: #fff; color: #1a365d; padding: 0.75rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
{{ if eq .Page.Language.Lang "de" }}Mehr erfahren{{ else }}Learn More{{ end }}
</a>
</aside>