goon/app/templates/seo/scene.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

54 lines
2.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "seo/base.html" %}
{% set perf_names = performers|map(attribute="canonical_name")|list %}
{% block title %}{{ scene.title }}{% if studio %} {{ studio.name }}{% endif %} | Goon{% endblock %}
{% block description %}{% if scene.description %}{{ scene.description|truncate(155) }}{% else %}Watch {{ scene.title }}{% if perf_names %} with {{ perf_names|join(", ") }}{% endif %}{% if studio %} ({{ studio.name }}){% endif %}. Available on {{ sources|length }} source{{ 's' if sources|length != 1 else '' }} — indexed by Goon.{% endif %}{% endblock %}
{% block og_type %}video.other{% endblock %}
{% block og_image %}{% if thumb %}<meta property="og:image" content="{{ thumb if thumb.startswith('http') else base_url ~ thumb }}">{% endif %}{% endblock %}
{% block jsonld %}
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"VideoObject",
"name": {{ scene.title|tojson }},
"description": {{ (scene.description or scene.title)|tojson }},
{% if thumb %}"thumbnailUrl": {{ (thumb if thumb.startswith('http') else base_url ~ thumb)|tojson }},{% endif %}
{% if scene.release_date %}"uploadDate": {{ scene.release_date.isoformat()|tojson }},{% endif %}
{% if iso_duration %}"duration": {{ iso_duration|tojson }},{% endif %}
{% if perf_names %}"actor": {{ perf_names|map("string")|list|tojson }},{% endif %}
{% if studio %}"productionCompany": {{ {"@type":"Organization","name": studio.name}|tojson }},{% endif %}
"url": {{ canonical|tojson }}
}
</script>
{% endblock %}
{% block content %}
<h1>{{ scene.title }}</h1>
<p class="meta">
{% if studio %}<a href="{{ base_url }}/studio/{{ studio.slug }}">{{ studio.name }}</a>{% endif %}
{% if scene.release_date %} · {{ scene.release_date }}{% endif %}
{% if scene.duration_sec %} · {{ (scene.duration_sec // 60) }} min{% endif %}
</p>
{% if performers %}
<p>Featuring:
{% for p in performers %}<a href="{{ base_url }}/p/{{ p.slug }}">{{ p.canonical_name }}</a>{% if not loop.last %}, {% endif %}{% endfor %}
</p>
{% endif %}
{% if scene.description %}<p>{{ scene.description }}</p>{% endif %}
<h2>Watch on {{ sources|length }} source{{ 's' if sources|length != 1 else '' }}</h2>
<div class="sources">
{% for src in sources %}
<a href="{{ src.page_url }}" rel="nofollow sponsored noopener" target="_blank">
{{ src.label }}{% if src.quality %} · {{ src.quality }}{% endif %} ↗</a>
{% endfor %}
</div>
{% if tags %}
<p class="tags" style="margin-top:20px">
{% for t in tags %}<span>#{{ t.name }}</span>{% if not loop.last %} {% endif %}{% endfor %}
</p>
{% endif %}
{% endblock %}