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:
303
layouts/shortcodes/child-safety-map.html
Normal file
303
layouts/shortcodes/child-safety-map.html
Normal 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>
|
||||
13
layouts/shortcodes/faq.html
Normal file
13
layouts/shortcodes/faq.html
Normal 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>
|
||||
13
layouts/shortcodes/vpn-cta.html
Normal file
13
layouts/shortcodes/vpn-cta.html
Normal 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>
|
||||
Reference in New Issue
Block a user