goon/app/templates/seo/base.html
jtrzupek 9c49a69a66 feat(seo): public HTML SEO router + templates; add CLAUDE.md; ignore .nimbalyst
- app/api/seo.py (+ app/templates/seo/*): publiczny HTML SEO router (programmatic
  entity long-tail: performer/studio/scene/landing/2257), bez api-key. Importowany
  przez main.py — wymagany do uruchomienia, dotąd untracked. Opsec-clean (brak
  VPS IP/sekretów).
- CLAUDE.md: instrukcje projektu (dotąd untracked).
- .gitignore: .nimbalyst/ (lokalne tracker-tooling, nie dla OSS repo).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:29:59 +02:00

105 lines
6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{# --- Analityka (gated na env, patrz seo.py) --- #}
{% if gsc_verify %}<meta name="google-site-verification" content="{{ gsc_verify }}">{% endif %}
{% if gtm_id %}<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{{ gtm_id }}');</script>{% endif %}
{# GA4 bezpośrednio przez gtag. Jeśli wpniesz GA4 wewnątrz GTM, odustaw GOON_GA4_ID
żeby nie liczyć podwójnie. #}
{% if ga4_id %}<script async src="https://www.googletagmanager.com/gtag/js?id={{ ga4_id }}"></script>
<script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}
gtag('js',new Date());gtag('config','{{ ga4_id }}');</script>{% endif %}
{# RTA label — sygnał dla filtrów rodzicielskich/SafeSearch że to adult. #}
<meta name="rating" content="RTA-5042-1996-1400-1577-RTA">
<meta name="rating" content="adult">
<title>{% block title %}Goon{% endblock %}</title>
<meta name="description" content="{% block description %}{% endblock %}">
<link rel="canonical" href="{{ canonical }}">
{# Indeksuj treść, ale nie follow-uj wychodzących linków do tubów jako endorsement. #}
<meta name="robots" content="{% block robots %}index, follow, max-image-preview:large{% endblock %}">
<meta property="og:site_name" content="Goon">
<meta property="og:type" content="{% block og_type %}website{% endblock %}">
<meta property="og:url" content="{{ canonical }}">
<meta property="og:title" content="{% block og_title %}{{ self.title() }}{% endblock %}">
{% block og_image %}{% endblock %}
<style>
:root { --bg:#1a1012; --fg:#ece0e2; --muted:#a98b90; --ox:#7b2230; --card:#241619; }
* { box-sizing:border-box; }
body { margin:0; background:var(--bg); color:var(--fg); font:16px/1.5 system-ui,sans-serif; }
a { color:#e88; text-decoration:none; } a:hover { text-decoration:underline; }
header, main, footer { max-width:1100px; margin:0 auto; padding:16px; }
header { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.wordmark { font-weight:800; letter-spacing:-.02em; font-size:22px; color:var(--fg); }
.cta { background:var(--ox); color:#fff; padding:9px 16px; border-radius:8px; font-weight:700; }
h1 { font-size:26px; margin:.2em 0; } h2 { font-size:18px; color:var(--muted); font-weight:600; }
.meta { color:var(--muted); font-size:14px; }
.grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:14px; margin-top:18px; }
.card { background:var(--card); border-radius:10px; overflow:hidden; }
.card img { width:100%; aspect-ratio:16/9; object-fit:cover; background:#000; }
.card .t { padding:8px 10px; font-size:13px; line-height:1.35; }
.card .s { color:var(--muted); font-size:12px; }
.sources a { display:inline-block; background:var(--card); padding:7px 12px; border-radius:7px; margin:4px 6px 0 0; }
.tags a { color:var(--muted); font-size:13px; margin-right:10px; }
footer { color:var(--muted); font-size:13px; border-top:1px solid #3a262b; margin-top:40px; }
#agegate { position:fixed; inset:0; background:#0c0709; display:flex; align-items:center;
justify-content:center; z-index:9999; text-align:center; padding:24px; }
/* `hidden` attribute must beat `#agegate{display:flex}` (id specificity),
otherwise the overlay can't be dismissed — see bug 2026-05-30. */
#agegate[hidden] { display:none; }
#agegate .box { max-width:440px; } #agegate h2 { color:var(--fg); }
#agegate button { background:var(--ox); color:#fff; border:0; padding:12px 22px; border-radius:8px;
font-size:16px; font-weight:700; cursor:pointer; margin:8px; }
#agegate .leave { background:#333; }
</style>
{% block jsonld %}{% endblock %}
</head>
<body>
{% if gtm_id %}<noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{ gtm_id }}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>{% endif %}
<header>
<a class="wordmark" href="{{ base_url }}/">GOON</a>
<a class="cta" href="/static/app-release.apk" rel="nofollow" onclick="goonTrackDownload('header')">Get the app</a>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>Goon is a scene metadata aggregator — we link out to the original sources and do
not host or stream any content. <a href="{{ base_url }}/2257">18 U.S.C. 2257</a> ·
<a href="https://github.com/goon-foss/goon">open source</a></p>
<p>All models were 18 or older at the time of depiction. Content links point to
third-party sites; Goon stores no media.</p>
</footer>
{# Age-gate: overlay tylko dla ludzi. Treść jest w DOM, więc crawler ją widzi. #}
<div id="agegate" hidden>
<div class="box">
<div class="wordmark" style="font-size:28px">GOON</div>
<h2>This site contains adult content</h2>
<p>You must be 18 years or older (21 where applicable) to enter.</p>
<button onclick="goonAgeOk()">I am 18 or older — Enter</button>
<button class="leave" onclick="location.href='https://www.google.com'">Leave</button>
</div>
</div>
<script>
// Conversion: APK download click → event to GA4 (gtag, direct) and to GTM
// (dataLayer, for ad-network pixels). Safe when analytics is disabled.
function goonTrackDownload(src){
try{ if(window.gtag) gtag('event','download_click',{source:src}); }catch(e){}
try{ if(window.dataLayer) window.dataLayer.push({event:'download_click',source:src}); }catch(e){}
}
function goonAgeOk(){ document.cookie="age_ok=1;path=/;max-age=2592000;samesite=lax";
document.getElementById('agegate').hidden=true; document.body.style.overflow=''; }
(function(){ if(!/(^|;\s*)age_ok=1/.test(document.cookie)){
document.getElementById('agegate').hidden=false; document.body.style.overflow='hidden'; } })();
</script>
</body>
</html>