Compare commits

...
9 Commits
Author SHA1 Message Date
lucashahmann 3af888cfa4 Graphyfy
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-30 16:57:19 +01:00
lucashahmann a07b8be38a SEO
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-30 16:45:29 +01:00
lucashahmann 36a73f6b63 SEO 2026-10-30 16:45:28 +01:00
lucashahmann 8cf5ed7b86 Added EPK
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-19 22:23:47 +02:00
lucashahmann f98785b26a Deploy Script Windows
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-19 22:16:44 +02:00
lucashahmann fe2bae803b Added Lukas
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-19 21:32:08 +02:00
lucashahmann 44866d1b87 Addedf Releases Site
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-19 21:23:17 +02:00
lucashahmann 09a4754d51 Added Releases
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-19 21:17:43 +02:00
lucashahmann 2a2dc030b7 Kommende TBA Shows
Deploy Hugo Site / deploy (push) Canceled after 0s
2026-10-19 21:07:45 +02:00
88 changed files with 1853 additions and 85 deletions

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
# Deepwater Survival – Website & EPK
Punkrock-Band aus Trier. Hugo-Seite, Deutsch, deployt mit `deploy.ps1`.
## Website
- Inhalte: `content/` (Startseite `_index.md`, Band `about.md`, Musik `music/_index.md`)
- Shows: eine Datei pro Show in `content/shows/` (`title`, `date`, `location`, `poster`; `tba: true` für noch unbekannte Termine; optional `city` und `address` für die Event-Daten bei Google, nur bestätigte Adressen)
- SEO: JSON-LD in `layouts/partials/schema.html` (Band auf der Startseite, kommende Shows auf `/shows/`), eigene Sitemap ohne Show-Einzelseiten in `layouts/_default/sitemap.xml`
- Release-Cover: `releases/JJJJMMTT_[Single|Album]_[Name].jpg`. Titel und Datum kommen aus dem Dateinamen.
- Design: `assets/css/main.css`. Farben `--deep #081226`, `--bolt #fff200` (Blitz-Gelb), `--red #e5232b`; Schriften Big Shoulders Display (Überschriften) und Archivo (Text), liegen in `static/fonts/`.
- Links und E-Mail stehen in `hugo.toml` unter `[params]`.
## EPK (Electronic Press Kit)
- Vorlage: `epk/epk.html`, 4 A4-Seiten: Cover, Bio, Band & Musik, Live & Kontakt
- PDF erzeugen: `.\epk\build.ps1` → `epk/Deepwater_Survival_EPK.pdf`
- Das EPK nutzt Bilder und Schriften direkt aus `static/` und `releases/` (relative Pfade `../`).
- Die Inhalte sind **von Hand** aus der Website übernommen, nichts wird automatisch synchronisiert. Wenn sich Shows, Releases, Besetzung oder Texte auf der Website ändern, `epk.html` mitpflegen (vor allem „Nächste Shows“ und „Bisherige Shows“ auf Seite 4 sowie die Zahl „15+ Shows“ auf dem Cover) und das PDF neu erzeugen.
- Jede Seite ist fest 210 × 297 mm mit `overflow: hidden`. Nach Änderungen das PDF prüfen, ob Inhalt abgeschnitten wird.
- Keine Fakten erfinden (Zuschauerzahlen, „ausverkauft“, Presse-Zitate), nur was die Band bestätigt hat.
- Fotos: Lukas Ittenbach (@shot__itt), im EPK immer nennen.
+141 -35
View File
@@ -338,6 +338,7 @@ p { margin: 0 0 1em; }
font-weight: 600; font-weight: 600;
color: var(--mist); color: var(--mist);
} }
.live__sub--past { margin-top: 4rem; }
.flyer-wall { .flyer-wall {
display: grid; display: grid;
@@ -398,6 +399,51 @@ p { margin: 0 0 1em; }
hyphens: auto; hyphens: auto;
} }
/* Platzhalter-Plakat für Shows, die noch nicht angekündigt sind (tba: true) */
.tba {
position: relative;
container-type: inline-size;
background: var(--bolt);
color: var(--deep);
}
.tba__bolt {
position: absolute;
top: 6%;
right: 4%;
width: 46%;
height: auto;
fill: var(--deep);
}
.tba__big {
position: absolute;
left: 6%;
bottom: 4%;
font-family: var(--font-display);
font-weight: 900;
font-size: 6rem;
font-size: 42cqi;
line-height: .8;
}
.tba__band {
position: absolute;
left: -10%;
right: -10%;
top: 50%;
padding: .45rem 0 .35rem;
background: var(--deep);
color: var(--bolt);
transform: translateY(-60%) rotate(-8deg);
text-align: center;
font-family: var(--font-display);
font-weight: 800;
font-size: 1.35rem;
font-size: 10cqi;
letter-spacing: .04em;
line-height: 1;
text-transform: uppercase;
white-space: nowrap;
}
.flyer__caption { padding: .9rem .35rem 0; } .flyer__caption { padding: .9rem .35rem 0; }
.flyer__caption time { font-size: .9rem; font-weight: 600; } .flyer__caption time { font-size: .9rem; font-weight: 600; }
.flyer__caption h3 { .flyer__caption h3 {
@@ -476,26 +522,90 @@ p { margin: 0 0 1em; }
} }
.group-photo img { width: 100%; } .group-photo img { width: 100%; }
/* ---------- Musik ---------- */ .crew { padding-block: clamp(4rem, 10vw, 6rem); }
.crew > .display { margin-bottom: 2rem; }
.release { .crew__body {
display: grid; display: grid;
gap: 2.5rem 4rem; gap: 2rem 3rem;
padding-bottom: clamp(3rem, 8vw, 5rem); align-items: end;
} }
@media (min-width: 56rem) { @media (min-width: 40rem) {
.release { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; } .crew__body { grid-template-columns: minmax(0, 18rem) minmax(0, 1fr); }
} }
.release__kind { margin-bottom: .5rem; color: var(--mist); font-weight: 600; } .crew__photo {
.release__title { display: grid;
place-items: center;
max-width: 18rem;
aspect-ratio: 4 / 5;
overflow: hidden;
background: var(--deep-2);
border: 2px solid var(--line);
}
.crew__photo img { width: 100%; height: 100%; object-fit: cover; }
.crew__initials {
font-family: var(--font-display); font-family: var(--font-display);
font-weight: 900; font-weight: 900;
font-size: clamp(4rem, 12vw, 8rem); font-size: 6rem;
line-height: 1;
color: var(--bolt);
}
.crew__name {
font-family: var(--font-display);
font-weight: 900;
font-size: clamp(2.5rem, 6vw, 4rem);
line-height: .9;
text-transform: uppercase;
}
.crew__role { margin: .5rem 0 1rem; color: var(--mist); font-weight: 600; }
.crew__text { max-width: 45ch; margin-bottom: 1.75rem; }
.button--handle { text-transform: none; }
/* ---------- Musik ---------- */
.album {
display: grid;
gap: 3rem 5rem;
padding-bottom: clamp(4rem, 10vw, 7rem);
}
@media (min-width: 56rem) {
.album { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); align-items: center; }
}
/* Die Platte rutscht aus der Hülle */
.album__sleeve {
position: relative;
width: 72%;
max-width: 30rem;
}
.album__cover {
position: relative;
z-index: 1;
box-shadow: 0 2rem 3rem -1.5rem rgba(0, 0, 0, .8);
}
.album__cover img { width: 100%; }
.album__vinyl {
position: absolute;
inset: 3%;
border-radius: 50%;
background:
radial-gradient(circle, var(--deep) 0 2.5%, var(--red) 2.6% 17%, #1a1a1a 17.5% 19%, transparent 19.5%),
repeating-radial-gradient(circle, #111 0 1px, #1c1c1c 1.5px 3px);
box-shadow: inset 0 0 0 2px #000, 0 1rem 2rem -1rem rgba(0, 0, 0, .8);
transform: translateX(34%);
transition: transform .6s cubic-bezier(.2, .8, .2, 1);
}
.album__sleeve:hover .album__vinyl { transform: translateX(42%) rotate(40deg); }
.album__kind { margin-bottom: .75rem; color: var(--mist); font-weight: 600; }
.album__title {
font-family: var(--font-display);
font-weight: 900;
font-size: clamp(4rem, 11vw, 8rem);
line-height: .82; line-height: .82;
text-transform: uppercase; text-transform: uppercase;
color: var(--bolt); color: var(--bolt);
} }
.release__text { max-width: 40ch; margin: 1.5rem 0 2rem; font-size: 1.15rem; } .album__text { max-width: 40ch; margin: 1.5rem 0 2rem; font-size: 1.15rem; }
.spotify { .spotify {
display: flex; display: flex;
@@ -514,39 +624,35 @@ p { margin: 0 0 1em; }
.spotify iframe { display: block; width: 100%; border: 0; } .spotify iframe { display: block; width: 100%; border: 0; }
.spotify.is-loaded { padding: 0; border: 0; background: none; } .spotify.is-loaded { padding: 0; border: 0; background: none; }
.singles { padding-bottom: clamp(3rem, 8vw, 5rem); } .discography,
.singles > .display { margin-bottom: 1.5rem; } .listen { padding-bottom: clamp(4rem, 10vw, 6rem); }
.discography > .display,
.listen > .display { margin-bottom: 2rem; }
.tracklist { .covers {
max-width: 40rem; display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
gap: 2.5rem 2rem;
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
counter-reset: track;
} }
.tracklist li { @media (max-width: 34rem) {
display: flex; .covers { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem 1rem; }
align-items: baseline;
gap: 1rem;
padding: .9rem 0;
border-bottom: 1px solid var(--line);
counter-increment: track;
} }
.tracklist li::before { .cover__img { aspect-ratio: 1; background: var(--deep-2); box-shadow: 0 1.25rem 2rem -1rem rgba(0, 0, 0, .7); }
content: counter(track); .cover__img img { width: 100%; height: 100%; object-fit: cover; }
min-width: 1.5rem; .cover__title {
color: var(--mist); margin-top: 1rem;
font-variant-numeric: tabular-nums;
}
.tracklist__title {
flex: 1;
font-family: var(--font-display); font-family: var(--font-display);
font-weight: 800; font-weight: 900;
font-size: 1.75rem; font-size: clamp(1.4rem, 3vw, 1.9rem);
line-height: .95;
text-transform: uppercase; text-transform: uppercase;
line-height: 1;
} }
.tracklist__year { color: var(--mist); font-variant-numeric: tabular-nums; } .cover__meta { margin: .35rem 0 0; font-size: .95rem; color: var(--mist); }
.listen .spotify { max-width: 40rem; }
.elsewhere { padding-bottom: clamp(4rem, 10vw, 7rem); } .elsewhere { padding-bottom: clamp(4rem, 10vw, 7rem); }
.elsewhere > .display { margin-bottom: 1.5rem; } .elsewhere > .display { margin-bottom: 1.5rem; }
+6
View File
@@ -17,5 +17,11 @@ members:
role: "Bass" role: "Bass"
image: "/img/about/Felix_compressed.jpg" image: "/img/about/Felix_compressed.jpg"
groupImage: "/img/about/Gruppenbild_compressed.jpg" groupImage: "/img/about/Gruppenbild_compressed.jpg"
crew:
heading: "Hinter der Kamera"
name: "Lukas Ittenbach"
role: "Video und Fotografie"
image: "/img/about/Lukas_Ittenbach.jpg"
text: "Von Lukas stammen die Fotos und Videos von Deepwater Survival."
--- ---
Vier Leute, zwei Gitarren, ein Bass, ein Schlagzeug. Deepwater Survival sind Olly, Lucas, Ahrens und Felix aus Trier. Vier Leute, zwei Gitarren, ein Bass, ein Schlagzeug. Deepwater Survival sind Olly, Lucas, Ahrens und Felix aus Trier.
+2 -13
View File
@@ -1,17 +1,6 @@
--- ---
title: "Musik" title: "Musik"
description: "Das Debütalbum „Ocean Tales“ und alle Singles von Deepwater Survival." description: "Das Debütalbum „Ocean Tales“ und alle Singles von Deepwater Survival."
album: albumText: "Unser Debütalbum. Mit dabei sind auch die Singles „My Own Home“, „Chirus“, „Let It Go“ und „Addiction“."
title: "Ocean Tales"
kind: "Debütalbum"
year: 2025
text: "Alle bisherigen Singles sind fast unverändert auf dem Album gelandet."
singles:
- title: "Chirus"
year: 2023
- title: "Let It Go"
year: 2024
- title: "Addiction"
- title: "My Own Home"
--- ---
Unsere Releases, Singles und Alben. Alle Releases, vom ersten Song bis zum Debütalbum.
@@ -3,4 +3,5 @@ title: "Pink Future"
date: 2024-06-07 date: 2024-06-07
location: Palastgarten Trier location: Palastgarten Trier
poster: /img/shows/2024_Pink_Future.jpeg poster: /img/shows/2024_Pink_Future.jpeg
aliases: ["/shows/2024_pink_future-copy/"]
--- ---
+7
View File
@@ -0,0 +1,7 @@
---
title: "Halloween Rock"
date: 2026-10-31
location: Gutweiler
poster: /img/shows/2026_Halloween.jpeg
aliases: ["/shows/2026_haloween/"]
---
-6
View File
@@ -1,6 +0,0 @@
---
title: "Halloween Rock"
date: 2026-10-31
location: Gutweiler
poster: /img/shows/2026_Haloween.jpeg
---
+5
View File
@@ -0,0 +1,5 @@
---
title: "???" # optional, sonst steht "Neue Show" da
date: 2026-12-23 # Pflicht, dient zum Sortieren # optional, sonst steht "Ort folgt" da
tba: true
---
+63
View File
@@ -0,0 +1,63 @@
# Baut die Seite lokal und lädt sie auf den Webserver.
# Ersetzt den Gitea-Workflow (.gitea/workflows/deploy.yml) für manuelle Deploys.
#
# .\deploy.ps1 # bauen und hochladen
# .\deploy.ps1 -DryRun # nur bauen und packen, nichts hochladen
# .\deploy.ps1 -Key C:\pfad\zum\key # bestimmten SSH-Key verwenden
# # (Standard: ~\.ssh\deepwater_deploy, falls vorhanden)
param(
[string]$Server = "webserver.hahmann-trier.local",
[int]$Port = 8147,
[string]$User = "gitea-deploy",
[string]$Target = "/var/www/www-deepwatersurvival-de",
[string]$Key = "",
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
Set-Location $PSScriptRoot
function Assert-Ok($step) {
if ($LASTEXITCODE -ne 0) { throw "$step fehlgeschlagen (Exit-Code $LASTEXITCODE)" }
}
$defaultKey = Join-Path $HOME ".ssh\deepwater_deploy"
if (-not $Key -and (Test-Path $defaultKey)) { $Key = $defaultKey }
$sshOpts = @("-o", "StrictHostKeyChecking=accept-new")
if ($Key) { $sshOpts += @("-i", $Key) }
Write-Host "1/4 Baue Seite mit Hugo ..."
hugo --minify --cleanDestinationDir
Assert-Ok "Hugo-Build"
Write-Host "2/4 Packe public/ ..."
$archive = Join-Path $env:TEMP "deepwatersurvival-site.tgz"
& "$env:SystemRoot\System32\tar.exe" -czf $archive -C public .
Assert-Ok "Packen"
Write-Host (" {0:N1} MB" -f ((Get-Item $archive).Length / 1MB))
if ($DryRun) {
Write-Host "DryRun: nichts hochgeladen. Archiv liegt unter $archive"
exit 0
}
$stamp = Get-Date -Format "yyyyMMddHHmmss"
$remoteDir = "/tmp/deepwatersurvival-$stamp"
$remote = "$User@$Server"
Write-Host "3/4 Lade hoch nach $remote ..."
scp -P $Port @sshOpts $archive "${remote}:$remoteDir.tgz"
Assert-Ok "Upload"
Write-Host "4/4 Entpacke und gleiche $Target ab ..."
# rsync --delete entfernt auf dem Server Dateien, die es lokal nicht mehr gibt (wie im Workflow).
$remoteCmd = "set -e; mkdir -p $remoteDir; tar -xzf $remoteDir.tgz -C $remoteDir; " +
"rsync -rt --delete --chmod=D755,F644 $remoteDir/ $Target/; " +
"rm -rf $remoteDir $remoteDir.tgz"
ssh -p $Port @sshOpts $remote $remoteCmd
Assert-Ok "Abgleich auf dem Server"
Remove-Item $archive
Write-Host "Fertig: https://www.deepwatersurvival.de/"
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
# Erzeugt das EPK-PDF aus epk.html (Chrome oder Edge headless).
#
# .\epk\build.ps1
$ErrorActionPreference = "Stop"
Set-Location $PSScriptRoot
$browser = @(
"C:\Program Files\Google\Chrome\Application\chrome.exe",
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
) | Where-Object { Test-Path $_ } | Select-Object -First 1
if (-not $browser) { throw "Weder Chrome noch Edge gefunden." }
$html = (Resolve-Path "epk.html").Path
$pdf = Join-Path $PSScriptRoot "Deepwater_Survival_EPK.pdf"
if (Test-Path $pdf) { Remove-Item $pdf }
# Start-Process -Wait, weil chrome.exe sonst zurückkehrt, bevor das PDF geschrieben ist
Start-Process -FilePath $browser -Wait -WindowStyle Hidden -ArgumentList @(
"--headless=new", "--disable-gpu", "--no-pdf-header-footer",
"--allow-file-access-from-files", "--virtual-time-budget=5000",
"--print-to-pdf=`"$pdf`"", "`"file:///$($html -replace '\\','/')`""
)
if (-not (Test-Path $pdf)) { throw "PDF wurde nicht erzeugt." }
Write-Host "EPK erzeugt: $pdf"
+410
View File
@@ -0,0 +1,410 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Deepwater Survival – EPK</title>
<style>
@font-face { font-family: "Big Shoulders Display"; src: url("../static/fonts/big-shoulders-display-latin-800-normal.woff2") format("woff2"); font-weight: 800; }
@font-face { font-family: "Big Shoulders Display"; src: url("../static/fonts/big-shoulders-display-latin-900-normal.woff2") format("woff2"); font-weight: 900; }
@font-face { font-family: "Archivo"; src: url("../static/fonts/archivo-latin-400-normal.woff2") format("woff2"); font-weight: 400; }
@font-face { font-family: "Archivo"; src: url("../static/fonts/archivo-latin-400-italic.woff2") format("woff2"); font-weight: 400; font-style: italic; }
@font-face { font-family: "Archivo"; src: url("../static/fonts/archivo-latin-600-normal.woff2") format("woff2"); font-weight: 600; }
:root {
--deep: #081226;
--deep-2: #0f1f42;
--line: #22386a;
--bolt: #fff200;
--red: #e5232b;
--foam: #eef1f6;
--mist: #9fb0cf;
--display: "Big Shoulders Display", Impact, sans-serif;
--body: "Archivo", Arial, sans-serif;
}
@page { size: A4; margin: 0; }
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
background: var(--deep);
color: var(--foam);
font-family: var(--body);
font-size: 10.5pt;
line-height: 1.55;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
p { margin: 0 0 .8em; }
h1, h2, h3 { margin: 0; line-height: .95; }
.page {
position: relative;
width: 210mm;
height: 297mm;
overflow: hidden;
page-break-after: always;
break-after: page;
background: var(--deep);
}
.page:last-child { page-break-after: auto; break-after: auto; }
.inner { padding: 16mm 16mm 0; }
.display {
font-family: var(--display);
font-weight: 900;
text-transform: uppercase;
letter-spacing: .01em;
}
.kicker {
font-family: var(--display);
font-weight: 800;
text-transform: uppercase;
letter-spacing: .12em;
font-size: 11pt;
color: var(--bolt);
}
.h2 { font-size: 40pt; margin: 2mm 0 6mm; }
.mist { color: var(--mist); }
strong { color: var(--foam); font-weight: 600; }
.pagefoot {
position: absolute;
left: 16mm; right: 16mm; bottom: 9mm;
display: flex;
justify-content: space-between;
font-size: 8pt;
color: var(--mist);
border-top: 1px solid var(--line);
padding-top: 3mm;
letter-spacing: .04em;
}
/* ---------- Cover ---------- */
.cover-photo {
position: absolute; inset: 0;
width: 100%; height: 100%;
object-fit: cover;
object-position: 50% 60%;
}
.cover-shade {
position: absolute; inset: 0;
background:
linear-gradient(180deg, rgba(8,18,38,.92) 0%, rgba(8,18,38,.15) 30%, rgba(8,18,38,.2) 55%, rgba(8,18,38,.97) 82%);
}
.cover-top {
position: absolute; top: 16mm; left: 16mm; right: 16mm;
display: flex; justify-content: space-between; align-items: baseline;
}
.cover-logo {
position: absolute; top: 30mm; left: 50%;
transform: translateX(-50%);
width: 150mm;
}
.cover-bottom {
position: absolute; left: 16mm; right: 16mm; bottom: 16mm;
}
.cover-title { font-size: 66pt; line-height: .85; }
.cover-title span { color: var(--bolt); }
.cover-sub {
margin-top: 5mm;
font-size: 13pt;
max-width: 130mm;
}
.slash {
display: inline-block;
background: var(--bolt);
color: var(--deep);
padding: 1.2mm 4mm .8mm;
transform: skewX(-14deg);
font-family: var(--display);
font-weight: 900;
text-transform: uppercase;
font-size: 12pt;
letter-spacing: .06em;
}
.slash > span { display: inline-block; transform: skewX(14deg); }
.cover-meta {
margin-top: 8mm;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 4mm;
border-top: 2px solid var(--bolt);
padding-top: 4mm;
}
.cover-meta dt { font-size: 7.5pt; text-transform: uppercase; letter-spacing: .12em; color: var(--mist); }
.cover-meta dd { margin: .5mm 0 0; font-family: var(--display); font-weight: 800; font-size: 15pt; text-transform: uppercase; line-height: 1.05; }
/* ---------- Bio ---------- */
.bio-photo {
width: 100%;
height: 112mm;
object-fit: cover;
object-position: 50% 45%;
clip-path: polygon(0 0, 100% 0, 100% 86%, 0 100%);
}
.bio-grid {
display: grid;
grid-template-columns: 1fr 58mm;
gap: 10mm;
}
.lead {
font-size: 13pt;
line-height: 1.45;
}
.quote {
font-family: var(--display);
font-weight: 900;
text-transform: uppercase;
font-size: 24pt;
line-height: .95;
color: var(--bolt);
margin: 5mm 0 0;
}
.facts { border-left: 2px solid var(--red); padding-left: 5mm; }
.facts dt { font-size: 7.5pt; text-transform: uppercase; letter-spacing: .12em; color: var(--mist); margin-top: 3.5mm; }
.facts dt:first-child { margin-top: 0; }
.facts dd { margin: .3mm 0 0; font-weight: 600; font-size: 10pt; line-height: 1.35; }
/* ---------- Band ---------- */
.members {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 4mm;
}
.member img {
width: 100%;
aspect-ratio: 2 / 3;
object-fit: cover;
filter: grayscale(1) contrast(1.05);
}
.member h3 { font-family: var(--display); font-weight: 900; text-transform: uppercase; font-size: 20pt; margin-top: 2.5mm; }
.member p { margin: .5mm 0 0; font-size: 8.5pt; color: var(--mist); line-height: 1.3; }
.album {
margin-top: 14mm;
display: grid;
grid-template-columns: 70mm 1fr;
gap: 8mm;
align-items: start;
}
.album img { width: 70mm; height: 70mm; box-shadow: 0 0 0 1px var(--line); }
.album .display { font-size: 34pt; margin: 1mm 0 3mm; }
.singles {
margin-top: 12mm;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 3.5mm;
}
.single img { width: 100%; aspect-ratio: 1; object-fit: cover; box-shadow: 0 0 0 1px var(--line); }
.single b { display: block; margin-top: 1.5mm; font-family: var(--display); font-weight: 800; text-transform: uppercase; font-size: 11pt; line-height: 1; }
.single span { font-size: 7.5pt; color: var(--mist); }
/* ---------- Live & Kontakt ---------- */
.live-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10mm;
}
.next {
background: var(--deep-2);
border-left: 3px solid var(--bolt);
padding: 4mm 5mm;
margin-bottom: 3mm;
}
.next .date { font-family: var(--display); font-weight: 900; font-size: 20pt; color: var(--bolt); line-height: 1; }
.next .name { font-weight: 600; font-size: 11pt; }
.next .where { font-size: 9pt; color: var(--mist); }
.history { list-style: none; margin: 0; padding: 0; }
.history li {
display: grid;
grid-template-columns: 17mm 1fr;
gap: 3mm;
padding: 1.6mm 0;
border-bottom: 1px solid var(--line);
font-size: 9pt;
line-height: 1.3;
}
.history li span:first-child { color: var(--mist); font-variant-numeric: tabular-nums; }
.history .loc { color: var(--mist); }
.posters {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 3mm;
margin-top: 8mm;
}
.posters img { width: 100%; height: auto; box-shadow: 0 0 0 1px var(--line); }
.contact {
position: absolute;
left: 0; right: 0; bottom: 0;
height: 66mm;
background: var(--bolt);
color: var(--deep);
padding: 12mm 16mm 0;
clip-path: polygon(0 18%, 100% 0, 100% 100%, 0 100%);
}
.contact-grid {
margin-top: 6mm;
display: grid;
grid-template-columns: 1.5fr 1fr;
gap: 8mm;
align-items: end;
}
.contact .display { font-size: 38pt; }
.contact .mail { font-family: var(--display); font-weight: 900; font-size: 22pt; text-transform: lowercase; }
.contact ul { list-style: none; margin: 0; padding: 0; font-size: 9pt; line-height: 1.6; }
.contact ul b { display: inline-block; width: 22mm; font-weight: 600; }
.contact small { display: block; margin-top: 3mm; font-size: 7.5pt; opacity: .75; }
</style>
</head>
<body>
<!-- ================= 1 · Cover ================= -->
<section class="page">
<img class="cover-photo" src="../static/img/AlbumReleaseParty_Stage_compressed.jpg" alt="">
<div class="cover-shade"></div>
<div class="cover-top">
<span class="kicker">Electronic Press Kit</span>
<span class="kicker" style="color:var(--mist)">2026</span>
</div>
<img class="cover-logo" src="../static/img/logo-crop.png" alt="Deepwater Survival">
<div class="cover-bottom">
<span class="slash"><span>Punkrock aus Trier</span></span>
<h1 class="display cover-title" style="margin-top:5mm">Roh, laut<br><span>und ehrlich.</span></h1>
<p class="cover-sub">Energiegeladener Punkrock, ehrliche Texte und unverblümte Direktheit. Debütalbum <strong>„Ocean Tales“</strong> überall, wo es Musik gibt.</p>
<dl class="cover-meta">
<div><dt>Genre</dt><dd>Punkrock</dd></div>
<div><dt>Herkunft</dt><dd>Trier</dd></div>
<div><dt>Debütalbum</dt><dd>Ocean Tales<br>2025</dd></div>
<div><dt>Live seit</dt><dd>2022 · 15+ Shows</dd></div>
</dl>
</div>
</section>
<!-- ================= 2 · Bio ================= -->
<section class="page">
<img class="bio-photo" src="../static/img/about/Gruppenbild_compressed.jpg" alt="Deepwater Survival Gruppenbild">
<div class="inner" style="padding-top:8mm">
<span class="kicker">Über die Band</span>
<h2 class="display h2">Punk mit Haltung</h2>
<div class="bio-grid">
<div>
<p class="lead">Mit energiegeladenem Punkrock, ehrlichen Texten und unverblümter Direktheit meldet sich <strong>Deepwater Survival</strong> zurück. Die Band aus Trier spielt einen Sound, der roh, mitreißend und ehrlich ist – für alteingesessene Punkfans genauso wie für neue Hörer:innen.</p>
<p>Bevor 2025 das Debütalbum <strong>„Ocean Tales“</strong> erschien, kamen bereits die Singles „Chirus“ (2023), „Let It Go“ (2024), „Addiction“ und „My Own Home“ heraus. Die Songs sind fast unverändert auf dem Album gelandet und zeigen die musikalische und emotionale Bandbreite der Band.</p>
<p>Die Texte drehen sich um Identität, Zugehörigkeit, Abschied und Neuanfang. Die Musik lädt dazu ein, laut mitzusingen, nachzudenken und gemeinsam mit der Band ein Stück Erinnerung und Hoffnung zu teilen.</p>
<p class="quote">Klar, ungeschönt, direkt.</p>
<p class="mist" style="margin-top:1.5mm">Für alle, die Musik nicht nur hören, sondern fühlen wollen.</p>
</div>
<dl class="facts">
<dt>Besetzung</dt>
<dd>Olly · Lucas · Ahrens · Felix</dd>
<dt>Instrumente</dt>
<dd>Zwei Gitarren, Bass, Schlagzeug, Gesang</dd>
<dt>Releases</dt>
<dd>1 Album, 5 Singles</dd>
<dt>Bühnen u. a.</dt>
<dd>Altstadtfest Trier, Tufa Trier, Rothaus Trier, Palastgarten Trier, Moselrock</dd>
<dt>Streaming</dt>
<dd>Spotify, YouTube und alle gängigen Plattformen</dd>
</dl>
</div>
</div>
<div class="pagefoot"><span>DEEPWATER SURVIVAL · EPK</span><span>Foto: Lukas Ittenbach (@shot__itt)</span></div>
</section>
<!-- ================= 3 · Band & Musik ================= -->
<section class="page">
<div class="inner">
<span class="kicker">Die Band</span>
<h2 class="display h2">Vier Leute. Ein Lärm.</h2>
<div class="members">
<div class="member"><img src="../static/img/about/Olly_compressed.jpg" alt=""><h3>Olly</h3><p>Leadgitarre &amp; Gesang</p></div>
<div class="member"><img src="../static/img/about/Lucas_compressed.jpg" alt=""><h3>Lucas</h3><p>Rhythmusgitarre</p></div>
<div class="member"><img src="../static/img/about/Ahrens_compressed.jpg" alt=""><h3>Ahrens</h3><p>Schlagzeug</p></div>
<div class="member"><img src="../static/img/about/Felix_compressed.jpg" alt=""><h3>Felix</h3><p>Bass</p></div>
</div>
<div class="album">
<img src="../releases/20250718_Album_OceanTales.jpg" alt="Ocean Tales Cover">
<div>
<span class="kicker">Debütalbum · 18.07.2025</span>
<h2 class="display">Ocean Tales</h2>
<p>Das erste Album von Deepwater Survival – gefeiert mit einer Release Party im Rothaus Trier. Mit dabei sind auch die Singles „My Own Home“, „Chirus“, „Let It Go“ und „Addiction“.</p>
<p class="mist" style="font-size:9pt">Spotify: open.spotify.com/artist/2TQ9HNBTNCmUthpg9ippHs</p>
</div>
</div>
<div class="singles">
<div class="single"><img src="../releases/20250627_Single_Addiction.jpg" alt=""><b>Addiction</b><span>Single · 2025</span></div>
<div class="single"><img src="../releases/20240619_Single_Let_It_Go.jpg" alt=""><b>Let It Go</b><span>Single · 2024</span></div>
<div class="single"><img src="../releases/20231118_Single_Chirus.jpg" alt=""><b>Chirus</b><span>Single · 2023</span></div>
<div class="single"><img src="../releases/20230630_Single_I'm_So_Glad.jpg" alt=""><b>I’m So Glad</b><span>Single · 2023</span></div>
<div class="single"><img src="../releases/20230421_Single_My_Own_Home.jpg" alt=""><b>My Own Home</b><span>Single · 2023</span></div>
</div>
</div>
<div class="pagefoot"><span>DEEPWATER SURVIVAL · EPK</span><span>deepwatersurvival.de</span></div>
</section>
<!-- ================= 4 · Live & Kontakt ================= -->
<section class="page">
<div class="inner">
<span class="kicker">Live</span>
<h2 class="display h2">On Stage</h2>
<div class="live-grid">
<div>
<p class="mist" style="font-size:8pt;text-transform:uppercase;letter-spacing:.12em;margin-bottom:2mm">Nächste Shows</p>
<div class="next"><div class="date">31.10.2026</div><div class="name">Halloween Rock</div><div class="where">Gutweiler</div></div>
<div class="next"><div class="date">23.12.2026</div><div class="name">Neue Show</div><div class="where">Details folgen</div></div>
<div class="posters" style="grid-template-columns:repeat(2,1fr);margin-top:5mm">
<img src="../static/img/shows/2026_Altstadtfest.jpeg" alt="">
<img src="../static/img/shows/2025_Album_Release_Party.jpeg" alt="">
</div>
</div>
<div>
<p class="mist" style="font-size:8pt;text-transform:uppercase;letter-spacing:.12em;margin-bottom:2mm">Bisherige Shows</p>
<ul class="history">
<li><span>07/2026</span><span>Highway to Kell <span class="loc">· Kell</span></span></li>
<li><span>06/2026</span><span>Altstadtfest Trier <span class="loc">· Hauptmarkt Bühne</span></span></li>
<li><span>05/2026</span><span>Lucky´s Luke <span class="loc">· Trier</span></span></li>
<li><span>08/2025</span><span>Bullenhitze <span class="loc">· Salmtal</span></span></li>
<li><span>07/2025</span><span>Album Release Party <span class="loc">· Rothaus Trier</span></span></li>
<li><span>02/2025</span><span>Riez Kapellen-Contest <span class="loc">· Riez Rockbar, Bausendorf</span></span></li>
<li><span>12/2024</span><span>Rock im Gehege <span class="loc">· Piesbach</span></span></li>
<li><span>07/2024</span><span>Rock für Ruanda <span class="loc">· Butzweiler</span></span></li>
<li><span>06/2024</span><span>Pink Future <span class="loc">· Palastgarten Trier</span></span></li>
<li><span>09/2023</span><span>Pink Future <span class="loc">· Skatehalle Trier West</span></span></li>
<li><span>05/2023</span><span>Moselrock <span class="loc">· Wasserliesch</span></span></li>
<li><span>12/2022</span><span>Tefftival <span class="loc">· Tufa Trier</span></span></li>
<li><span>08/2022</span><span>JUKUFE Light <span class="loc">· Skatehalle Trier</span></span></li>
<li><span>07/2022</span><span>Rock im Gehege <span class="loc">· Piesbach</span></span></li>
<li><span>07/2022</span><span>Konz wird Laut <span class="loc">· Haus der Jugend Konz</span></span></li>
</ul>
</div>
</div>
</div>
<div class="contact">
<div class="contact-grid">
<div>
<h2 class="display">Booking &amp; Presse</h2>
<div class="mail">info@deepwatersurvival.de</div>
</div>
<div>
<ul>
<li><b>Web</b>deepwatersurvival.de</li>
<li><b>Instagram</b>@deepwatersurvival</li>
<li><b>YouTube</b>@deepwatersurvival730</li>
<li><b>Spotify</b>Deepwater Survival</li>
</ul>
<small>Fotos &amp; Videos: Lukas Ittenbach · instagram.com/shot__itt</small>
</div>
</div>
</div>
</section>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
{
"excludes": [
"themes/",
"themes/**",
"*.jpg",
"*.jpeg",
"*.png",
"*.gif",
"*.svg",
"*.pdf"
]
}
+1
View File
@@ -0,0 +1 @@
{"0": "Templates & Design", "1": "Band, EPK & Regeln", "2": "Gitea Deploy Workflow", "3": "Datenschutz & Impressum", "4": "Show-Schema & Mosel-Gigs", "5": "Shows ↔ EPK Sync", "6": "Pink Future & Skatehalle", "7": "Trierer Umland-Shows", "8": "Rock im Gehege", "9": "Tefftival", "10": "Album Release Party", "11": "Riez Kapellen-Contest", "12": "Altstadtfest Trier", "13": "Halloween Rock", "14": "Deploy-Skript", "15": "Spotify Loader (site.js)", "16": "EPK PDF Build"}
+1
View File
@@ -0,0 +1 @@
C:\Program Files\Python312\python.exe
+1
View File
@@ -0,0 +1 @@
D:\code\www-deepwatersurvival-de
+135
View File
@@ -0,0 +1,135 @@
# Graph Report - www-deepwatersurvival-de (2026-10-30)
## Corpus Check
- Corpus is ~8,291 words - fits in a single context window. You may not need a graph.
## Summary
- 132 nodes · 189 edges · 17 communities (10 shown, 7 thin omitted)
- Extraction: 62% EXTRACTED · 37% INFERRED · 1% AMBIGUOUS · INFERRED: 70 edges (avg confidence: 0.91)
- Token cost: 219,106 input · 0 output
## Community Hubs (Navigation)
- Templates & Design
- Band, EPK & Regeln
- Gitea Deploy Workflow
- Datenschutz & Impressum
- Show-Schema & Mosel-Gigs
- Shows ↔ EPK Sync
- Pink Future & Skatehalle
- Trierer Umland-Shows
- Rock im Gehege
- Tefftival
- Album Release Party
- Riez Kapellen-Contest
- Altstadtfest Trier
- Halloween Rock
## God Nodes (most connected - your core abstractions)
1. `Show Front Matter Schema (title, date, location, poster, tba)` - 19 edges
2. `Shows Section Index` - 18 edges
3. `Base Template (baseof.html)` - 12 edges
4. `epk.html EPK Template` - 10 edges
5. `CLAUDE.md Project Guide (Website & EPK)` - 7 edges
6. `EPK Page 3: Band & Musik (Members, Ocean Tales, 5 Singles)` - 7 edges
7. `Music Page Layout (featured album, discography)` - 7 edges
8. `site.Params (email, spotify, instagram, youtube, photographer)` - 7 edges
9. `[params] links, email, Spotify/Instagram/YouTube` - 6 edges
10. `EPK Page 4: Live & Kontakt (Nächste/Bisherige Shows, Booking)` - 6 edges
## Surprising Connections (you probably didn't know these)
- `Spotify Player Click-to-Load (no data before consent)` --conceptually_related_to--> `[params] links, email, Spotify/Instagram/YouTube` [INFERRED]
content/Datenschutz.md → hugo.toml
- `Single: I'm So Glad (2023)` --conceptually_related_to--> `Singles: Chirus, Let It Go, Addiction, My Own Home` [AMBIGUOUS]
epk/epk.html → content/_index.md
- `Default Content Archetype (draft, date, title from filename)` --conceptually_related_to--> `Show Front Matter Schema (title, date, location, poster, tba)` [INFERRED]
archetypes/default.md → content/shows/2026_Tefftival.md
- `EPK Page 3: Band & Musik (Members, Ocean Tales, 5 Singles)` --implements--> `Release Cover Naming Convention (JJJJMMTT_[Single|Album]_[Name].jpg)` [INFERRED]
epk/epk.html → CLAUDE.md
- `Photo Credit Rule (Lukas Ittenbach @shot__itt always credited)` --rationale_for--> `EPK Page 4: Live & Kontakt (Nächste/Bisherige Shows, Booking)` [INFERRED]
CLAUDE.md → epk/epk.html
## Import Cycles
- None detected.
## Hyperedges (group relationships)
- **Upcoming shows after 2026-10-30 (EPK 'Nächste Shows')** — content_shows_2026_halloween_show, content_shows_2026_tefftival_show, content_shows__index_shows [INFERRED 0.75]
- **Shows in the city of Trier** — content_shows_2022_jukufe_light_show, content_shows_2023_pink_future_show, content_shows_2024_pink_future_show, content_shows_2025_album_release_party_show, content_shows_2026_altstadtfest_trier_show, content_shows_2026_luke_show [INFERRED 0.75]
- **Website content manually mirrored into EPK** — claude_epk_manual_sync, content__index_band_bio, content_about_members, content_music__index_music_page, epk_epk_document [INFERRED 0.85]
- **EPK four A4 pages** — epk_epk_cover_page, epk_epk_bio_page, epk_epk_band_music_page, epk_epk_live_contact_page [EXTRACTED 1.00]
- **Privacy-conscious site choices (local fonts, click-to-load Spotify, DSGVO)** — content_datenschutz_local_fonts, content_datenschutz_spotify_click_to_load, content_datenschutz_dsgvo_rights, content_datenschutz_hosting_1blu [INFERRED 0.75]
- **Show listing rendering (home, shows page, card, JSON-LD events)** — layouts_index, layouts_shows_list, layouts_partials_show_card, layouts_partials_schema_musicevent [INFERRED 0.85]
- **Release cover filename parsing feeding music page and album schema** — layouts_partials_releases, layouts_partials_releases_filename_convention, layouts_music_list, layouts_partials_schema_musicgroup [EXTRACTED 1.00]
- **SEO layer (meta tags, JSON-LD, robots, show redirects)** — layouts__default_baseof_seo_meta, layouts_partials_schema, layouts_robots, layouts_shows_single [INFERRED 0.75]
## Communities (17 total, 7 thin omitted)
### Community 0 - "Templates & Design"
Cohesion: 0.11
Nodes (27): Main Stylesheet (main.css), Album Sleeve Vinyl Slide-Out Effect, Design Tokens (--deep, --bolt, --red, fonts, --slant), Flyer Wall (tilted posters with gaffa tape), 404 Page Template (Abgesoffen), Band Page Layout (members, group photo, crew), Crew Section (photographer portrait / initials fallback), Base Template (baseof.html) (+19 more)
### Community 1 - "Band, EPK & Regeln"
Cohesion: 0.13
Nodes (22): Deepwater Survival (Punkrock-Band aus Trier), EPK (Electronic Press Kit, 4 A4 pages), epk/build.ps1 (PDF build), Hugo Website (deutsch, deploy.ps1), CLAUDE.md Project Guide (Website & EPK), Band Bio Text (Identität, Zugehörigkeit, Abschied, Neuanfang), Home Page Content (Punk mit Haltung), Ocean Tales (Debütalbum 2025) (+14 more)
### Community 2 - "Gitea Deploy Workflow"
Cohesion: 0.11
Nodes (17): image, container, env, runs-on, steps, http_proxy, https_proxy, no_proxy (+9 more)
### Community 3 - "Datenschutz & Impressum"
Cohesion: 0.22
Nodes (7): Design System (--deep, --bolt, --red; Big Shoulders Display + Archivo), DSGVO Betroffenenrechte und Rechtsgrundlagen, Externes Hosting bei 1blu GmbH, Datenschutzerklärung, Disclaimer (Inhalte, externe Links, Urheberrecht, Nutzungsbedingungen), Impressum (Lucas Hahmann, Trier), EPK CSS Tokens (:root --deep, --bolt, --red, fonts)
### Community 4 - "Show-Schema & Mosel-Gigs"
Cohesion: 0.25
Nodes (8): Default Content Archetype (draft, date, title from filename), Moselrock, Wasserliesch, Salmtal, Bullenhitze, Kell, Highway to Kell, Show Front Matter Schema (title, date, location, poster, tba)
### Community 5 - "Shows ↔ EPK Sync"
Cohesion: 0.38
Nodes (5): SEO: JSON-LD schema partial and custom sitemap, EPK Page 1: Cover (Roh, laut und ehrlich; 15+ Shows), EPK Page 4: Live & Kontakt (Nächste/Bisherige Shows, Booking), Show History 2022-2026 (15 shows, e.g. Tefftival Tufa, Moselrock, Altstadtfest), Upcoming Shows (31.10.2026 Halloween Rock Gutweiler; 23.12.2026 TBA)
### Community 6 - "Pink Future & Skatehalle"
Cohesion: 0.29
Nodes (7): JUKUFE Light, Skatehalle Trier, Pink Future (recurring), Pink Future 2023, Skatehalle Trier West, Palastgarten Trier, Pink Future 2024
### Community 7 - "Trierer Umland-Shows"
Cohesion: 0.29
Nodes (7): Haus der Jugend Konz, Konz wird Laut, Butzweiler, Rock für Ruanda, Lucky´s Luke, Trier, Shows Section Index
### Community 8 - "Rock im Gehege"
Cohesion: 0.67
Nodes (4): Piesbach, Rock im Gehege (recurring), Rock im Gehege 2022, Rock im Gehege 2024
### Community 9 - "Tefftival"
Cohesion: 0.50
Nodes (4): Tefftival 2022, Tefftival (recurring, Dec 23), Tufa, Tefftival 2026 (TBA)
## Ambiguous Edges - Review These
- `Singles: Chirus, Let It Go, Addiction, My Own Home` → `Single: I'm So Glad (2023)` [AMBIGUOUS]
epk/epk.html · relation: conceptually_related_to
## Knowledge Gaps
- **27 isolated node(s):** `Default Content Archetype (draft, date, title from filename)`, `Haus der Jugend Konz`, `Tufa`, `Wasserliesch`, `Palastgarten Trier` (+22 more)
These have ≤1 connection - possible missing edges or undocumented components. (Counts symbols only; 45 node(s) total have ≤1 connection when file, concept and rationale nodes are included.)
- **7 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Show Front Matter Schema (title, date, location, poster, tba)` connect `Show-Schema & Mosel-Gigs` to `Pink Future & Skatehalle`, `Trierer Umland-Shows`, `Rock im Gehege`, `Tefftival`, `Album Release Party`, `Riez Kapellen-Contest`, `Altstadtfest Trier`, `Halloween Rock`?**
_High betweenness centrality (0.037) - this node is a cross-community bridge._
- **Are the 18 inferred relationships involving `Show Front Matter Schema (title, date, location, poster, tba)` (e.g. with `Default Content Archetype (draft, date, title from filename)` and `JUKUFE Light`) actually correct?**
_`Show Front Matter Schema (title, date, location, poster, tba)` has 18 INFERRED edges - model-reasoned connections that need verification._
- **What connects `Default Content Archetype (draft, date, title from filename)`, `Haus der Jugend Konz`, `Tufa` to the rest of the system?**
_27 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Templates & Design` be split into smaller, more focused modules?**
_Cohesion score 0.10837438423645321 - nodes in this community are weakly interconnected._
- **Why does `epk.html EPK Template` connect `Band, EPK & Regeln` to `Datenschutz & Impressum`, `Shows ↔ EPK Sync`?**
_High betweenness centrality (0.036) - this node is a cross-community bridge._
- **Are the 18 inferred relationships involving `Shows Section Index` (e.g. with `JUKUFE Light` and `Konz wird Laut`) actually correct?**
_`Shows Section Index` has 18 INFERRED edges - model-reasoned connections that need verification._
### Low-confidence Hints
_AMBIGUOUS edges — the extractor was unsure. Verify before acting on these._
- **What is the exact relationship between `Singles: Chirus, Let It Go, Addiction, My Own Home` and `Single: I'm So Glad (2023)`?**
_Edge tagged AMBIGUOUS (relation: conceptually_related_to) - confidence is low._
@@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_deploy_ps1", "label": "deploy.ps1", "file_type": "code", "source_file": "deploy.ps1", "source_location": "L1"}, {"id": "$graphify-root$_deploy_assert_ok", "label": "Assert-Ok()", "file_type": "code", "source_file": "deploy.ps1", "source_location": "L21"}], "edges": [{"source": "$graphify-root$_deploy_ps1", "target": "$graphify-root$_deploy_assert_ok", "relation": "contains", "confidence": "EXTRACTED", "source_file": "deploy.ps1", "source_location": "L21", "weight": 1.0}, {"source": "$graphify-root$_deploy_ps1", "target": "$graphify-root$_deploy_assert_ok", "relation": "calls", "confidence": "EXTRACTED", "source_file": "deploy.ps1", "source_location": "L33", "weight": 1.0}], "raw_calls": [{"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Set-Location", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L19"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Join-Path", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L25"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Test-Path", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L26"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L31"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "hugo", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L32"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L35"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Join-Path", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L36"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L39"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Get-Item", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L39"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L42"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Get-Date", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L46"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L50"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "scp", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L51"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L54"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "ssh", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L59"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Remove-Item", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L62"}, {"caller_nid": "$graphify-root$_deploy_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "deploy.ps1", "source_location": "L63"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_epk_build_ps1", "label": "build.ps1", "file_type": "code", "source_file": "epk/build.ps1", "source_location": "L1"}], "edges": [], "raw_calls": [{"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Set-Location", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L6"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Where-Object", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L11"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Test-Path", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L11"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Select-Object", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L11"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Resolve-Path", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L14"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Join-Path", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L15"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Test-Path", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L16"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Remove-Item", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L16"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Start-Process", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L19"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Test-Path", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L24"}, {"caller_nid": "$graphify-root$_epk_build_ps1", "callee": "Write-Host", "is_member_call": false, "source_file": "epk/build.ps1", "source_location": "L26"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_gitea_workflows_deploy_yml", "label": "deploy.yml", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L1"}, {"id": "$graphify-root$_gitea_workflows_deploy_name", "label": "name", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L1"}, {"id": "$graphify-root$_gitea_workflows_deploy_on", "label": "on", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L3"}, {"id": "$graphify-root$_gitea_workflows_deploy_on_push", "label": "push", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L4"}, {"id": "$graphify-root$_gitea_workflows_deploy_push_branches", "label": "branches", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L5"}, {"id": "$graphify-root$_gitea_workflows_deploy_jobs", "label": "jobs", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L8"}, {"id": "$graphify-root$_gitea_workflows_deploy_jobs_deploy", "label": "deploy", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L9"}, {"id": "$graphify-root$_gitea_workflows_deploy_deploy_runs_on", "label": "runs-on", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L10"}, {"id": "$graphify-root$_gitea_workflows_deploy_deploy_container", "label": "container", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L11"}, {"id": "$graphify-root$_gitea_workflows_deploy_container_image", "label": "image", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L12"}, {"id": "$graphify-root$_gitea_workflows_deploy_deploy_env", "label": "env", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L14"}, {"id": "$graphify-root$_gitea_workflows_deploy_env_http_proxy", "label": "http_proxy", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L15"}, {"id": "$graphify-root$_gitea_workflows_deploy_env_https_proxy", "label": "https_proxy", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L16"}, {"id": "$graphify-root$_gitea_workflows_deploy_env_no_proxy", "label": "no_proxy", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L17"}, {"id": "$graphify-root$_gitea_workflows_deploy_deploy_steps", "label": "steps", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L19"}, {"id": "$graphify-root$_gitea_workflows_deploy_steps_name", "label": "name", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L20"}, {"id": "$graphify-root$_gitea_workflows_deploy_steps_uses", "label": "uses", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L21"}, {"id": "$graphify-root$_gitea_workflows_deploy_steps_run", "label": "run", "file_type": "code", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L24"}], "edges": [{"source": "$graphify-root$_gitea_workflows_deploy_yml", "target": "$graphify-root$_gitea_workflows_deploy_name", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L1", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_yml", "target": "$graphify-root$_gitea_workflows_deploy_on", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L3", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_on", "target": "$graphify-root$_gitea_workflows_deploy_on_push", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L4", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_on_push", "target": "$graphify-root$_gitea_workflows_deploy_push_branches", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L5", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_yml", "target": "$graphify-root$_gitea_workflows_deploy_jobs", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L8", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_jobs", "target": "$graphify-root$_gitea_workflows_deploy_jobs_deploy", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L9", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_jobs_deploy", "target": "$graphify-root$_gitea_workflows_deploy_deploy_runs_on", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".gitea/workflows/deploy.yml", "source_location": "L10", "weight": 1.0}, {"source": "$graphify-root$_gitea_workflows_deploy_jobs_deploy", "Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_index", "label": "Homepage Template (hero, intro, live, booking)", "file_type": "code", "source_file": "layouts/index.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_index", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/index.html", "source_location": "L1", "weight": 1.0}, {"source": "layouts_index", "target": "layouts_partials_img", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/index.html", "source_location": "L8", "weight": 1.0}, {"source": "layouts_index", "target": "layouts_partials_show_card", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/index.html", "source_location": "L39", "weight": 1.0}, {"source": "layouts_index", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/index.html", "source_location": "L42", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "epk_epk_document", "label": "epk.html EPK Template", "file_type": "code", "source_file": "epk/epk.html", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_css_tokens", "label": "EPK CSS Tokens (:root --deep, --bolt, --red, fonts)", "file_type": "code", "source_file": "epk/epk.html", "source_location": "L13", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_cover_page", "label": "EPK Page 1: Cover (Roh, laut und ehrlich; 15+ Shows)", "file_type": "code", "source_file": "epk/epk.html", "source_location": "L267", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_bio_page", "label": "EPK Page 2: Bio (Punk mit Haltung, Facts)", "file_type": "code", "source_file": "epk/epk.html", "source_location": "L289", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_band_music_page", "label": "EPK Page 3: Band & Musik (Members, Ocean Tales, 5 Singles)", "file_type": "code", "source_file": "epk/epk.html", "source_location": "L320", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_live_contact_page", "label": "EPK Page 4: Live & Kontakt (N\u00e4chste/Bisherige Shows, Booking)", "file_type": "code", "source_file": "epk/epk.html", "source_location": "L353", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_show_history", "label": "Show History 2022-2026 (15 shows, e.g. Tefftival Tufa, Moselrock, Altstadtfest)", "file_type": "concept", "source_file": "epk/epk.html", "source_location": "L369", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_upcoming_shows", "label": "Upcoming Shows (31.10.2026 Halloween Rock Gutweiler; 23.12.2026 TBA)", "file_type": "concept", "source_file": "epk/epk.html", "source_location": "L360", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "epk_epk_single_im_so_glad", "label": "Single: I'm So Glad (2023)", "file_type": "concept", "source_file": "epk/epk.html", "source_location": "L345", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "epk_epk_document", "target": "epk_epk_css_tokens", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L13", "weight": 1.0}, {"source": "epk_epk_document", "target": "epk_epk_cover_page", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L267", "weight": 1.0}, {"source": "epk_epk_document", "target": "epk_epk_bio_page", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L289", "weight": 1.0}, {"source": "epk_epk_document", "target": "epk_epk_band_music_page", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L320", "weight": 1.0}, {"source": "epk_epk_document", "target": "epk_epk_live_contact_page", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L353", "weight": 1.0}, {"source": "epk_epk_live_contact_page", "target": "epk_epk_show_history", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L369", "weight": 1.0}, {"source": "epk_epk_live_contact_page", "target": "epk_epk_upcoming_shows", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L360", "weight": 1.0}, {"source": "epk_epk_band_music_page", "target": "content__index_ocean_tales", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L332", "weight": 1.0}, {"source": "epk_epk_band_music_page", "target": "content__index_singles", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L341", "weight": 1.0}, {"source": "epk_epk_band_music_page", "target": "epk_epk_single_im_so_glad", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html", "source_location": "L345", "weight": 1.0}, {"source": "epk_epk_band_music_page", "target": "claude_release_cover_naming", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "epk/epk.html", "source_location": "L332", "weight": 1.0}, {"source": "epk_epk_cover_page", "target": "epk_epk_show_history", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "epk/epk.html", "source_location": "L283", "weight": 1.0}, {"source"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2022_jukufe_light_show", "label": "JUKUFE Light", "file_type": "document", "source_file": "content/shows/2022_Jukufe_light.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2022-08-22", "location": "Skatehalle Trier"}, {"id": "content_shows_2022_jukufe_light_skatehalle_trier", "label": "Skatehalle Trier", "file_type": "concept", "source_file": "content/shows/2022_Jukufe_light.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2022_jukufe_light_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Jukufe_light.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_jukufe_light_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Jukufe_light.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_jukufe_light_show", "target": "content_shows_2022_jukufe_light_skatehalle_trier", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2022_Jukufe_light.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts__default_list", "label": "Default List Layout", "file_type": "code", "source_file": "layouts/_default/list.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts__default_list", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/_default/list.html", "source_location": "L1", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2022_konz_wird_laut_show", "label": "Konz wird Laut", "file_type": "document", "source_file": "content/shows/2022_Konz_wird_laut.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2022-07-09", "location": "Haus der Jugend Konz"}, {"id": "content_shows_2022_konz_wird_laut_haus_der_jugend_konz", "label": "Haus der Jugend Konz", "file_type": "concept", "source_file": "content/shows/2022_Konz_wird_laut.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2022_konz_wird_laut_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Konz_wird_laut.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_konz_wird_laut_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Konz_wird_laut.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_konz_wird_laut_show", "target": "content_shows_2022_konz_wird_laut_haus_der_jugend_konz", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2022_Konz_wird_laut.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2025_bullenhitze_show", "label": "Bullenhitze", "file_type": "document", "source_file": "content/shows/2025_Bullenhitze.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2025-08-30", "location": "Salmtal"}, {"id": "content_shows_2025_bullenhitze_salmtal", "label": "Salmtal", "file_type": "concept", "source_file": "content/shows/2025_Bullenhitze.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2025_bullenhitze_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2025_Bullenhitze.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2025_bullenhitze_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2025_Bullenhitze.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2025_bullenhitze_show", "target": "content_shows_2025_bullenhitze_salmtal", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2025_Bullenhitze.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2023_pink_future_show", "label": "Pink Future 2023", "file_type": "document", "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2023-09-15", "location": "Skatehalle Trier West"}, {"id": "content_shows_2023_pink_future_skatehalle_trier_west", "label": "Skatehalle Trier West", "file_type": "concept", "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_shows_2023_pink_future_pink_future_series", "label": "Pink Future (recurring)", "file_type": "concept", "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2023_pink_future_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2023_pink_future_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2023_pink_future_show", "target": "content_shows_2023_pink_future_skatehalle_trier_west", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2023_pink_future_show", "target": "content_shows_2023_pink_future_pink_future_series", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2023_pink_future_skatehalle_trier_west", "target": "content_shows_2022_jukufe_light_skatehalle_trier", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/shows/2023_Pink_Future.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2025_riez_kapellenkontest_show", "label": "Riez Kapellen-Contest", "file_type": "document", "source_file": "content/shows/2025_Riez_Kapellenkontest.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2025-02-01", "location": "Riez Rockbar, Bausendorf"}, {"id": "content_shows_2025_riez_kapellenkontest_riez_rockbar_bausendorf", "label": "Riez Rockbar, Bausendorf", "file_type": "concept", "source_file": "content/shows/2025_Riez_Kapellenkontest.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2025_riez_kapellenkontest_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2025_Riez_Kapellenkontest.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2025_riez_kapellenkontest_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2025_Riez_Kapellenkontest.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2025_riez_kapellenkontest_show", "target": "content_shows_2025_riez_kapellenkontest_riez_rockbar_bausendorf", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2025_Riez_Kapellenkontest.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows__index_shows", "label": "Shows Section Index", "file_type": "document", "source_file": "content/shows/_index.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "description": "Kommende Konzerte und alle bisherigen Shows von Deepwater Survival."}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "content/shows/_index.md", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "upcoming_shows_2026", "label": "Upcoming shows after 2026-10-30 (EPK 'N\u00e4chste Shows')", "nodes": ["content_shows_2026_halloween_show", "content_shows_2026_tefftival_show", "content_shows__index_shows"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/shows/_index.md"}, {"id": "trier_city_shows", "label": "Shows in the city of Trier", "nodes": ["content_shows_2022_jukufe_light_show", "content_shows_2023_pink_future_show", "content_shows_2024_pink_future_show", "content_shows_2025_album_release_party_show", "content_shows_2026_altstadtfest_trier_show", "content_shows_2026_luke_show"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/shows/_index.md"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_music__index_music_page", "label": "Music Page (Musik)", "file_type": "document", "source_file": "content/music/_index.md", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_music__index_music_page", "target": "content__index_ocean_tales", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/music/_index.md", "source_location": "L3", "weight": 1.0}, {"source": "content_music__index_music_page", "target": "content__index_singles", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/music/_index.md", "source_location": "L4", "weight": 1.0}, {"source": "content_music__index_music_page", "target": "epk_epk_band_music_page", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/music/_index.md", "source_location": "L4", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts__default_single", "label": "Default Single Layout (legal prose)", "file_type": "code", "source_file": "layouts/_default/single.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts__default_single", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/_default/single.html", "source_location": "L1", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_releases", "label": "Releases Partial (parse cover filenames)", "file_type": "code", "source_file": "layouts/partials/releases.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "layouts_partials_releases_filename_convention", "label": "Release Filename Convention JJJJMMTT_Kind_Name.jpg", "file_type": "concept", "source_file": "layouts/partials/releases.html", "source_location": "L1-4", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_partials_releases_filename_convention", "target": "layouts_partials_releases", "relation": "rationale_for", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/releases.html", "source_location": "L1-4", "weight": 1.0}], "hyperedges": [{"id": "release_data_pipeline", "label": "Release cover filename parsing feeding music page and album schema", "nodes": ["layouts_partials_releases", "layouts_partials_releases_filename_convention", "layouts_music_list", "layouts_partials_schema_musicgroup"], "relation": "form", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/releases.html"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2022_tefftival_show", "label": "Tefftival 2022", "file_type": "document", "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2022-12-23", "location": "Tufa"}, {"id": "content_shows_2022_tefftival_tufa", "label": "Tufa", "file_type": "concept", "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_shows_2022_tefftival_tefftival_series", "label": "Tefftival (recurring, Dec 23)", "file_type": "concept", "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2022_tefftival_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_tefftival_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_tefftival_show", "target": "content_shows_2022_tefftival_tufa", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_tefftival_show", "target": "content_shows_2022_tefftival_tefftival_series", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2022_Tefftival.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_music_list", "label": "Music Page Layout (featured album, discography)", "file_type": "code", "source_file": "layouts/music/list.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "layouts_music_list_featured_release", "label": "Featured Release Selection (newest album, else newest release)", "file_type": "rationale", "source_file": "layouts/music/list.html", "source_location": "L3-5", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_music_list", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/music/list.html", "source_location": "L1", "weight": 1.0}, {"source": "layouts_music_list", "target": "layouts_partials_releases", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/music/list.html", "source_location": "L2", "weight": 1.0}, {"source": "layouts_music_list", "target": "layouts_partials_img", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/music/list.html", "source_location": "L17", "weight": 1.0}, {"source": "layouts_music_list", "target": "layouts_partials_spotify", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/music/list.html", "source_location": "L50", "weight": 1.0}, {"source": "layouts_music_list_featured_release", "target": "layouts_music_list", "relation": "rationale_for", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/music/list.html", "source_location": "L3", "weight": 1.0}, {"source": "layouts_music_list", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/music/list.html", "source_location": "L24", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_about_band_page", "label": "Band Page (about.md)", "file_type": "document", "source_file": "content/about.md", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_about_members", "label": "Band Members (Olly, Lucas, Ahrens, Felix)", "file_type": "concept", "source_file": "content/about.md", "source_location": "L6", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_about_crew_lukas_ittenbach", "label": "Crew: Lukas Ittenbach (Video und Fotografie)", "file_type": "concept", "source_file": "content/about.md", "source_location": "L20", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_about_band_page", "target": "content_about_members", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/about.md", "source_location": "L6", "weight": 1.0}, {"source": "content_about_band_page", "target": "content_about_crew_lukas_ittenbach", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/about.md", "source_location": "L20", "weight": 1.0}, {"source": "content_about_members", "target": "epk_epk_band_music_page", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/about.md", "source_location": "L6", "weight": 1.0}, {"source": "content_about_members", "target": "claude_deepwater_survival", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/about.md", "source_location": "L27", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2024_pink_future_show", "label": "Pink Future 2024", "file_type": "document", "source_file": "content/shows/2024_Pink_Future.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2024-06-07", "location": "Palastgarten Trier"}, {"id": "content_shows_2024_pink_future_palastgarten_trier", "label": "Palastgarten Trier", "file_type": "concept", "source_file": "content/shows/2024_Pink_Future.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2024_pink_future_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2024_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_pink_future_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2024_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_pink_future_show", "target": "content_shows_2024_pink_future_palastgarten_trier", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2024_Pink_Future.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_pink_future_show", "target": "content_shows_2023_pink_future_pink_future_series", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2024_Pink_Future.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_header", "label": "Header Partial (logo, main nav with aria-current)", "file_type": "code", "source_file": "layouts/partials/header.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2026_tefftival_show_front_matter_schema", "label": "Show Front Matter Schema (title, date, location, poster, tba)", "file_type": "concept", "source_file": "content/shows/2026_Tefftival.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "date is mandatory and used for sorting; title optional (fallback 'Neue Show'); location optional (fallback 'Ort folgt'); tba:true marks unannounced shows"}, {"id": "content_shows_2026_tefftival_show", "label": "Tefftival 2026 (TBA)", "file_type": "document", "source_file": "content/shows/2026_Tefftival.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2026-12-23", "location": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2026_tefftival_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Tefftival.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_tefftival_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Tefftival.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_tefftival_show", "target": "content_shows_2022_tefftival_tefftival_series", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/shows/2026_Tefftival.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_tefftival_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "rationale_for", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2026_Tefftival.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts__default_band", "label": "Band Page Layout (members, group photo, crew)", "file_type": "code", "source_file": "layouts/_default/band.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "layouts__default_band_crew_section", "label": "Crew Section (photographer portrait / initials fallback)", "file_type": "code", "source_file": "layouts/_default/band.html", "source_location": "L27-47", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts__default_band", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/_default/band.html", "source_location": "L1", "weight": 1.0}, {"source": "layouts__default_band", "target": "layouts_partials_img", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/band.html", "source_location": "L12", "weight": 1.0}, {"source": "layouts__default_band_crew_section", "target": "layouts__default_band", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/band.html", "source_location": "L27-47", "weight": 1.0}, {"source": "layouts__default_band_crew_section", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/band.html", "source_location": "L43", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2022_rock_im_gehege_show", "label": "Rock im Gehege 2022", "file_type": "document", "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2022-07-22", "location": "Piesbach"}, {"id": "content_shows_2022_rock_im_gehege_piesbach", "label": "Piesbach", "file_type": "concept", "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_shows_2022_rock_im_gehege_rock_im_gehege_series", "label": "Rock im Gehege (recurring)", "file_type": "concept", "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2022_rock_im_gehege_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_rock_im_gehege_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_rock_im_gehege_show", "target": "content_shows_2022_rock_im_gehege_piesbach", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2022_rock_im_gehege_show", "target": "content_shows_2022_rock_im_gehege_rock_im_gehege_series", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2022_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2026_halloween_show", "label": "Halloween Rock", "file_type": "document", "source_file": "content/shows/2026_Halloween.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2026-10-31", "location": "Gutweiler"}, {"id": "content_shows_2026_halloween_gutweiler", "label": "Gutweiler", "file_type": "concept", "source_file": "content/shows/2026_Halloween.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2026_halloween_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Halloween.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_halloween_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Halloween.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_halloween_show", "target": "content_shows_2026_halloween_gutweiler", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2026_Halloween.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_shows_single", "label": "Show Single Redirect (noindex, redirect to /shows/)", "file_type": "code", "source_file": "layouts/shows/single.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_shows_single", "target": "layouts_shows_list", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/shows/single.html", "source_location": "L7-8", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2026_luke_show", "label": "Lucky\u00b4s Luke", "file_type": "document", "source_file": "content/shows/2026_Luke.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2026-05-30", "location": "Trier"}, {"id": "content_shows_2026_luke_trier", "label": "Trier", "file_type": "concept", "source_file": "content/shows/2026_Luke.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2026_luke_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Luke.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_luke_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Luke.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_luke_show", "target": "content_shows_2026_luke_trier", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2026_Luke.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "claude_project_guide", "label": "CLAUDE.md Project Guide (Website & EPK)", "file_type": "document", "source_file": "CLAUDE.md", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_deepwater_survival", "label": "Deepwater Survival (Punkrock-Band aus Trier)", "file_type": "concept", "source_file": "CLAUDE.md", "source_location": "L3", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_hugo_website", "label": "Hugo Website (deutsch, deploy.ps1)", "file_type": "concept", "source_file": "CLAUDE.md", "source_location": "L3", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_shows_content_model", "label": "Shows Content Model (one file per show, tba, city/address)", "file_type": "rationale", "source_file": "CLAUDE.md", "source_location": "L8", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_seo_jsonld_sitemap", "label": "SEO: JSON-LD schema partial and custom sitemap", "file_type": "concept", "source_file": "CLAUDE.md", "source_location": "L9", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_release_cover_naming", "label": "Release Cover Naming Convention (JJJJMMTT_[Single|Album]_[Name].jpg)", "file_type": "rationale", "source_file": "CLAUDE.md", "source_location": "L10", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_design_system", "label": "Design System (--deep, --bolt, --red; Big Shoulders Display + Archivo)", "file_type": "concept", "source_file": "CLAUDE.md", "source_location": "L11", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_epk", "label": "EPK (Electronic Press Kit, 4 A4 pages)", "file_type": "concept", "source_file": "CLAUDE.md", "source_location": "L14", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_epk_manual_sync", "label": "EPK Manual Sync Rule (keep epk.html in step with website)", "file_type": "rationale", "source_file": "CLAUDE.md", "source_location": "L19", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_fixed_a4_overflow", "label": "Fixed A4 Page with overflow:hidden (check PDF for clipping)", "file_type": "rationale", "source_file": "CLAUDE.md", "source_location": "L20", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_no_invented_facts", "label": "No Invented Facts Policy (only band-confirmed claims)", "file_type": "rationale", "source_file": "CLAUDE.md", "source_location": "L21", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_photo_credit_rule", "label": "Photo Credit Rule (Lukas Ittenbach @shot__itt always credited)", "file_type": "rationale", "source_file": "CLAUDE.md", "source_location": "L22", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "claude_epk_build_script", "label": "epk/build.ps1 (PDF build)", "file_type": "code", "source_file": "CLAUDE.md", "source_location": "L17", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "claude_project_guide", "target": "claude_hugo_website", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L3", "weight": 1.0}, {"source": "claude_project_guide", "target": "claude_epk", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L14", "weight": 1.0}, {"source": "claude_hugo_website", "target": "claude_deepwater_survival", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L3", "weight": 1.0}, {"source": "claude_project_guide", "target": "content__index_home", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L7", "weight": 1.0}, {"source": "claude_project_guide", "target": "content_about_band_page", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L7", "weight": 1.0}, {"source": "claude_project_guide", "target": "content_music__index_music_page", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L7", "weight": 1.0}, {"source": "claude_project_guide", "target": "epk_epk_document", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CLAUDE.md", "source_location": "L16", "weight": 1.0}, {"source": "claude_epk_build_script", "target": "epk_epk_document", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "sLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2026_highway_to_kell_show", "label": "Highway to Kell", "file_type": "document", "source_file": "content/shows/2026_Highway_to_Kell.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2026-07-24", "location": "Kell"}, {"id": "content_shows_2026_highway_to_kell_kell", "label": "Kell", "file_type": "concept", "source_file": "content/shows/2026_Highway_to_Kell.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2026_highway_to_kell_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Highway_to_Kell.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_highway_to_kell_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Highway_to_Kell.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_highway_to_kell_show", "target": "content_shows_2026_highway_to_kell_kell", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2026_Highway_to_Kell.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2025_album_release_party_show", "label": "Album Release Party", "file_type": "document", "source_file": "content/shows/2025_Album_Release_Party.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2025-07-18", "location": "Rothaus Trier"}, {"id": "content_shows_2025_album_release_party_rothaus_trier", "label": "Rothaus Trier", "file_type": "concept", "source_file": "content/shows/2025_Album_Release_Party.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2025_album_release_party_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2025_Album_Release_Party.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2025_album_release_party_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2025_Album_Release_Party.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2025_album_release_party_show", "target": "content_shows_2025_album_release_party_rothaus_trier", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2025_Album_Release_Party.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content__index_home", "label": "Home Page Content (Punk mit Haltung)", "file_type": "document", "source_file": "content/_index.md", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content__index_band_bio", "label": "Band Bio Text (Identit\u00e4t, Zugeh\u00f6rigkeit, Abschied, Neuanfang)", "file_type": "concept", "source_file": "content/_index.md", "source_location": "L6", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content__index_ocean_tales", "label": "Ocean Tales (Deb\u00fctalbum 2025)", "file_type": "concept", "source_file": "content/_index.md", "source_location": "L8", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content__index_singles", "label": "Singles: Chirus, Let It Go, Addiction, My Own Home", "file_type": "concept", "source_file": "content/_index.md", "source_location": "L8", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content__index_home", "target": "content__index_band_bio", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/_index.md", "source_location": "L6", "weight": 1.0}, {"source": "content__index_band_bio", "target": "content__index_ocean_tales", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/_index.md", "source_location": "L8", "weight": 1.0}, {"source": "content__index_band_bio", "target": "content__index_singles", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/_index.md", "source_location": "L8", "weight": 1.0}, {"source": "content__index_singles", "target": "content__index_ocean_tales", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/_index.md", "source_location": "L8", "weight": 1.0}, {"source": "content__index_band_bio", "target": "epk_epk_bio_page", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/_index.md", "source_location": "L6", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "archetypes_default_archetype", "label": "Default Content Archetype (draft, date, title from filename)", "file_type": "code", "source_file": "archetypes/default.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "archetypes_default_archetype", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "archetypes/default.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts__default_baseof", "label": "Base Template (baseof.html)", "file_type": "code", "source_file": "layouts/_default/baseof.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "layouts__default_baseof_seo_meta", "label": "SEO / Open Graph Meta Tags", "file_type": "code", "source_file": "layouts/_default/baseof.html", "source_location": "L6-20", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts__default_baseof", "target": "layouts_partials_header", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/baseof.html", "source_location": "L30", "weight": 1.0}, {"source": "layouts__default_baseof", "target": "layouts_partials_footer", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/baseof.html", "source_location": "L34", "weight": 1.0}, {"source": "layouts__default_baseof", "target": "layouts_partials_schema", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/baseof.html", "source_location": "L26", "weight": 1.0}, {"source": "layouts__default_baseof_seo_meta", "target": "layouts__default_baseof", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/_default/baseof.html", "source_location": "L6-20", "weight": 1.0}, {"source": "layouts__default_baseof_seo_meta", "target": "layouts_partials_schema", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "layouts/_default/baseof.html", "source_location": "L6-26", "weight": 1.0}], "hyperedges": [{"id": "seo_layer", "label": "SEO layer (meta tags, JSON-LD, robots, show redirects)", "nodes": ["layouts__default_baseof_seo_meta", "layouts_partials_schema", "layouts_robots", "layouts_shows_single"], "relation": "form", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "layouts/_default/baseof.html"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2026_altstadtfest_trier_show", "label": "Altstadtfest Trier", "file_type": "document", "source_file": "content/shows/2026_Altstadtfest_Trier.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2026-06-28", "location": "Hauptmarkt B\u00fchne"}, {"id": "content_shows_2026_altstadtfest_trier_hauptmarkt_b\u00fchne", "label": "Hauptmarkt B\u00fchne", "file_type": "concept", "source_file": "content/shows/2026_Altstadtfest_Trier.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2026_altstadtfest_trier_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Altstadtfest_Trier.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_altstadtfest_trier_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2026_Altstadtfest_Trier.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2026_altstadtfest_trier_show", "target": "content_shows_2026_altstadtfest_trier_hauptmarkt_b\u00fchne", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2026_Altstadtfest_Trier.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_robots", "label": "robots.txt Template", "file_type": "code", "source_file": "layouts/robots.txt", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_robots", "target": "layouts__default_baseof_seo_meta", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "layouts/robots.txt", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_schema", "label": "JSON-LD Schema Partial", "file_type": "code", "source_file": "layouts/partials/schema.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "layouts_partials_schema_musicgroup", "label": "MusicGroup JSON-LD (band, members, albums)", "file_type": "concept", "source_file": "layouts/partials/schema.html", "source_location": "L8-39", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "layouts_partials_schema_musicevent", "label": "MusicEvent JSON-LD (upcoming non-TBA shows)", "file_type": "concept", "source_file": "layouts/partials/schema.html", "source_location": "L41-64", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_partials_schema", "target": "layouts_partials_releases", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/schema.html", "source_location": "L31", "weight": 1.0}, {"source": "layouts_partials_schema_musicgroup", "target": "layouts_partials_schema", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/schema.html", "source_location": "L8-39", "weight": 1.0}, {"source": "layouts_partials_schema_musicevent", "target": "layouts_partials_schema", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/schema.html", "source_location": "L41-64", "weight": 1.0}, {"source": "layouts_partials_schema_musicevent", "target": "layouts_partials_schema_musicgroup", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/schema.html", "source_location": "L54", "weight": 1.0}, {"source": "layouts_partials_schema_musicgroup", "target": "layouts__default_band", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/partials/schema.html", "source_location": "L23", "weight": 1.0}, {"source": "layouts_partials_schema_musicevent", "target": "layouts_shows_list", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "layouts/partials/schema.html", "source_location": "L41-43", "weight": 1.0}, {"source": "layouts_partials_schema", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/schema.html", "source_location": "L13-18", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_spotify", "label": "Spotify Consent Embed Partial (click-to-load)", "file_type": "code", "source_file": "layouts/partials/spotify.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_partials_spotify", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/spotify.html", "source_location": "L1", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_show_card", "label": "Show Card Partial (flyer / TBA poster)", "file_type": "code", "source_file": "layouts/partials/show-card.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_partials_show_card", "target": "layouts_partials_img", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/show-card.html", "source_location": "L14", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_shows_list", "label": "Shows List Layout (upcoming + archive by year)", "file_type": "code", "source_file": "layouts/shows/list.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_shows_list", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/shows/list.html", "source_location": "L1", "weight": 1.0}, {"source": "layouts_shows_list", "target": "layouts_partials_show_card", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/shows/list.html", "source_location": "L14", "weight": 1.0}, {"source": "layouts_shows_list", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/shows/list.html", "source_location": "L17", "weight": 1.0}], "hyperedges": [{"id": "show_rendering_flow", "label": "Show listing rendering (home, shows page, card, JSON-LD events)", "nodes": ["layouts_index", "layouts_shows_list", "layouts_partials_show_card", "layouts_partials_schema_musicevent"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "layouts/shows/list.html"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_impressum_page", "label": "Impressum (Lucas Hahmann, Trier)", "file_type": "document", "source_file": "content/Impressum.md", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_impressum_disclaimer", "label": "Disclaimer (Inhalte, externe Links, Urheberrecht, Nutzungsbedingungen)", "file_type": "concept", "source_file": "content/Impressum.md", "source_location": "L16", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_impressum_page", "target": "content_impressum_disclaimer", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/Impressum.md", "source_location": "L16", "weight": 1.0}, {"source": "content_impressum_page", "target": "content_datenschutz_page", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "content/Impressum.md", "source_location": "L8", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2024_rock_fuer_ruanda_show", "label": "Rock f\u00fcr Ruanda", "file_type": "document", "source_file": "content/shows/2024_Rock_fuer_Ruanda.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2024-07-22", "location": "Butzweiler"}, {"id": "content_shows_2024_rock_fuer_ruanda_butzweiler", "label": "Butzweiler", "file_type": "concept", "source_file": "content/shows/2024_Rock_fuer_Ruanda.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2024_rock_fuer_ruanda_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2024_Rock_fuer_Ruanda.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_rock_fuer_ruanda_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2024_Rock_fuer_Ruanda.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_rock_fuer_ruanda_show", "target": "content_shows_2024_rock_fuer_ruanda_butzweiler", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2024_Rock_fuer_Ruanda.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_datenschutz_page", "label": "Datenschutzerkl\u00e4rung", "file_type": "document", "source_file": "content/Datenschutz.md", "source_location": "L1", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_datenschutz_hosting_1blu", "label": "Externes Hosting bei 1blu GmbH", "file_type": "concept", "source_file": "content/Datenschutz.md", "source_location": "L31", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_datenschutz_local_fonts", "label": "Lokal gehostete Schriftarten (keine Google-Verbindung)", "file_type": "rationale", "source_file": "content/Datenschutz.md", "source_location": "L138", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_datenschutz_spotify_click_to_load", "label": "Spotify Player Click-to-Load (no data before consent)", "file_type": "rationale", "source_file": "content/Datenschutz.md", "source_location": "L141", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "content_datenschutz_dsgvo_rights", "label": "DSGVO Betroffenenrechte und Rechtsgrundlagen", "file_type": "concept", "source_file": "content/Datenschutz.md", "source_location": "L73", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_datenschutz_page", "target": "content_datenschutz_hosting_1blu", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/Datenschutz.md", "source_location": "L44", "weight": 1.0}, {"source": "content_datenschutz_page", "target": "content_datenschutz_local_fonts", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/Datenschutz.md", "source_location": "L138", "weight": 1.0}, {"source": "content_datenschutz_page", "target": "content_datenschutz_spotify_click_to_load", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/Datenschutz.md", "source_location": "L141", "weight": 1.0}, {"source": "content_datenschutz_page", "target": "content_datenschutz_dsgvo_rights", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/Datenschutz.md", "source_location": "L73", "weight": 1.0}, {"source": "content_datenschutz_local_fonts", "target": "claude_design_system", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "content/Datenschutz.md", "source_location": "L139", "weight": 1.0}], "hyperedges": [{"id": "privacy_by_design_choices", "label": "Privacy-conscious site choices (local fonts, click-to-load Spotify, DSGVO)", "nodes": ["content_datenschutz_local_fonts", "content_datenschutz_spotify_click_to_load", "content_datenschutz_dsgvo_rights", "content_datenschutz_hosting_1blu"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/Datenschutz.md"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2023_moselrock_show", "label": "Moselrock", "file_type": "document", "source_file": "content/shows/2023_Moselrock.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2023-05-27", "location": "Wasserliesch"}, {"id": "content_shows_2023_moselrock_wasserliesch", "label": "Wasserliesch", "file_type": "concept", "source_file": "content/shows/2023_Moselrock.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2023_moselrock_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2023_Moselrock.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2023_moselrock_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2023_Moselrock.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2023_moselrock_show", "target": "content_shows_2023_moselrock_wasserliesch", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2023_Moselrock.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_404", "label": "404 Page Template (Abgesoffen)", "file_type": "code", "source_file": "layouts/404.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_404", "target": "layouts__default_baseof", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "layouts/404.html", "source_location": "L1", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_footer", "label": "Footer Partial (contact, social, photographer credit)", "file_type": "code", "source_file": "layouts/partials/footer.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "site_params", "label": "site.Params (email, spotify, instagram, youtube, photographer)", "file_type": "concept", "source_file": "layouts/partials/footer.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "layouts_partials_footer", "target": "site_params", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/footer.html", "source_location": "L5-15", "weight": 1.0}], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "layouts_partials_img", "label": "Responsive Image Partial (WebP srcset)", "file_type": "code", "source_file": "layouts/partials/img.html", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [], "hyperedges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "content_shows_2024_rock_im_gehege_show", "label": "Rock im Gehege 2024", "file_type": "document", "source_file": "content/shows/2024_Rock_im_Gehege.md", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "date": "2024-12-11", "location": "Piesbach"}], "edges": [{"source": "content_shows__index_shows", "target": "content_shows_2024_rock_im_gehege_show", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2024_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_rock_im_gehege_show", "target": "content_shows_2026_tefftival_show_front_matter_schema", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "content/shows/2024_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_rock_im_gehege_show", "target": "content_shows_2022_rock_im_gehege_piesbach", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2024_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}, {"source": "content_shows_2024_rock_im_gehege_show", "target": "content_shows_2022_rock_im_gehege_rock_im_gehege_series", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "content/shows/2024_Rock_im_Gehege.md", "source_location": null, "weight": 1.0}], "hyperedges": []}
+1
View File
@@ -0,0 +1 @@
{".gitea/workflows/deploy.yml":{"size":1458,"mtime_ns":1792436508111369300,"indexed_at_ns":1793375385815978900,"word_count":129,"hashes":{".gitea/workflows/deploy.yml":"ed68d03614efce04be3bf55ba1e50b25ad79fb649ceca637fc4158fa0080df2a"}},"CLAUDE.md":{"size":1894,"mtime_ns":1793374882185068300,"indexed_at_ns":1793375386047068900,"word_count":248,"hashes":{"claude.md":"a007e39e610ee7e90f8086a1fc118f38027bb8e1e63a6e3f18e8a3f729a2de74"}},"archetypes/default.md":{"size":109,"mtime_ns":1779119062703551900,"indexed_at_ns":1793375386056320800,"word_count":21,"hashes":{"archetypes/default.md":"ad9cd1c0edd793a660ce78ee6129c748171fa3b6592ad9f25ed61eac81f30a29"}},"assets/js/site.js":{"size":717,"mtime_ns":1792428051347229000,"indexed_at_ns":1793375349820849300,"word_count":55},"content/Datenschutz.md":{"size":20501,"mtime_ns":1792427965125507300,"indexed_at_ns":1793375386058828200,"word_count":2652,"hashes":{"content/datenschutz.md":"ddb1ed36c1e59f7c77ab773dbbadb04628353ff37b7d1f7f219f69a5c4afc747"}},"content/Impressum.md":{"size":3050,"mtime_ns":1792427965124507000,"indexed_at_ns":1793375386060832800,"word_count":378,"hashes":{"content/impressum.md":"cbc0ca707890d890b7a23ffd6ad68bed4c2ec6e14fce478c4d134c7c55d3f11e"}},"content/_index.md":{"size":968,"mtime_ns":1792427946806149100,"indexed_at_ns":1793375386062829000,"word_count":135,"hashes":{"content/_index.md":"a9641b981c8177894357d1199d68fb1131076b23e7c04687db55f8ee0af8dc74"}},"content/about.md":{"size":886,"mtime_ns":1792438093690571400,"indexed_at_ns":1793375386064828200,"word_count":97,"hashes":{"content/about.md":"5e8459a4f345d974cbd460e54ac0b9429a6ca6207ff7c6cd1d33907c7475030e"}},"content/music/_index.md":{"size":299,"mtime_ns":1792437673297200200,"indexed_at_ns":1793375386066829100,"word_count":41,"hashes":{"content/music/_index.md":"3f300eca0e04e9c20b9d757385677d12e53b744224a3171ad8a67f372081d674"}},"content/shows/2022_Jukufe_light.md":{"size":130,"mtime_ns":1779119062706614200,"indexed_at_ns":1793375386069337000,"word_count":12,"hashes":{"content/shows/2022_jukufe_light.md":"1f2ec8f4bf35d894b35b69931ca5c9b8f4c344de4b9b255bc280d31f134349de"}},"content/shows/2022_Konz_wird_laut.md":{"size":138,"mtime_ns":1779119062707613700,"indexed_at_ns":1793375386071336800,"word_count":15,"hashes":{"content/shows/2022_konz_wird_laut.md":"2ed990a95efdd8caf9400f29fcce267ad43a8254af84edc3bf1ef17de9684607"}},"content/shows/2022_Rock_im_Gehege.md":{"size":126,"mtime_ns":1779119062707613700,"indexed_at_ns":1793375386073337600,"word_count":12,"hashes":{"content/shows/2022_rock_im_gehege.md":"7e3d0ae5d3b6d6d3ce461bceef1192743bb26099fd00e918b54e8498d22a1466"}},"content/shows/2022_Tefftival.md":{"size":112,"mtime_ns":1779119062707613700,"indexed_at_ns":1793375386075337000,"word_count":10,"hashes":{"content/shows/2022_tefftival.md":"4fc7b90a2cfd813e6b653e81b82208e07d7c226579d666ee74f07c9e092b856d"}},"content/shows/2023_Moselrock.md":{"size":120,"mtime_ns":1779119062707613700,"indexed_at_ns":1793375386076336700,"word_count":10,"hashes":{"content/shows/2023_moselrock.md":"e280dddce737cc1826c3b120534b0a298edf1a61076e2dbe2ecf9e5a81a1899f"}},"content/shows/2023_Pink_Future.md":{"size":129,"mtime_ns":1792427947035097000,"indexed_at_ns":1793375386079354600,"word_count":13,"hashes":{"content/shows/2023_pink_future.md":"3276889b42dbebcbe3d612601b785296af99f8d16b1e51bcce00c59188da2878"}},"content/shows/2024_Pink_Future.md":{"size":159,"mtime_ns":1793374815668919700,"indexed_at_ns":1793375386081354100,"word_count":14,"hashes":{"content/shows/2024_pink_future.md":"656824162f4490609650cc560bf533dea73f91dcc129afcafb7856a594037b87"}},"content/shows/2024_Rock_fuer_Ruanda.md":{"size":132,"mtime_ns":1779119062708613700,"indexed_at_ns":1793375386083353700,"word_count":12,"hashes":{"content/shows/2024_rock_fuer_ruanda.md":"d5d2792abf0c0447f581287abe1ffae7a83e4c1d88da199484062b3621331c51"}},"content/shows/2024_Rock_im_Gehege.md":{"size":126,"mtime_ns":1779119062708613700,"indexed_at_ns":1793375386085353700,"word_count":12,"hashes":{"content/shows/2024_rock_im_gehege.md":"f6c3c6f6df517c38f7eddf9c4db4b6f04ffd405146c7e4edbb42617bb3cca2cd"}},"content/shows/2025_Album_Release_Party.md":{"size":127,"mtime_ns":1792435816801631900,"indexed_at_ns":1793375386086354100,"word_count":13,"hashes":{"content/shows/2025_album_release_party.md":"a2bbe3ed8f10e656b7bdf7e4ec2fe46f6b709af35a777ed2f39fef74b2700746"}},"content/shows/2025_Bullenhitze.md":{"size":105,"mtime_ns":1792436153820609500,"indexed_at_ns":1793375386088862100,"word_count":10,"hashes":{"content/shows/2025_bullenhitze.md":"303d96901bce528e0524e560f56eede50e80955376736ba3141a2476003d5b5a"}},"content/shows/2025_Riez_Kapellenkontest.md":{"size":151,"mtime_ns":1792427947085265000,"indexed_at_ns":1793375386090862100,"word_count":13,"hashes":{"content/shows/2025_riez_kapellenkontest.md":"3376a10eefb2b55c4473f0181e16b3a6319934819347192e65ee2d378f75b36b"}},"content/shows/2026_Altstadtfest_Trier.md":{"size":123,"mtime_ns":1792435301873360300,"indexed_at_ns":17933753860Line truncated
+12
View File
@@ -0,0 +1,12 @@
{
"runs": [
{
"date": "2026-10-30T15:53:50.702625+00:00",
"input_tokens": 219106,
"output_tokens": 0,
"files": 47
}
],
"total_input_tokens": 219106,
"total_output_tokens": 0
}
+474
View File
@@ -0,0 +1,474 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>graphify - graphify-out/graph.html</title>
<script src="https://unpkg.com/vis-network@9.1.6/standalone/umd/vis-network.min.js"
integrity="sha384-Ux6phic9PEHJ38YtrijhkzyJ8yQlH8i/+buBR8s3mAZOJrP1gwyvAcIYl3GWtpX1"
crossorigin="anonymous"></script>
<style>
:root {
--bg: #0f0f1a; --panel: #1a1a2e; --border: #2a2a4e; --input-border: #3a3a5e;
--text: #e0e0e0; --text-2: #aaa; --text-3: #ccc; --muted: #555; --count: #666;
--neighbor-border: #333; --node-label: #ffffff;
}
[data-theme="light"] {
--bg: #ffffff; --panel: #f8f9fa; --border: #d9dee5; --input-border: #c3cad4;
--text: #222222; --text-2: #666666; --text-3: #333333; --muted: #888888; --count: #777777;
--neighbor-border: #ccc; --node-label: #222222;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: var(--bg); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; display: flex; height: 100vh; overflow: hidden; }
#graph { flex: 1; }
#sidebar { width: 280px; background: var(--panel); border-left: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; }
#search-wrap { padding: 12px; border-bottom: 1px solid var(--border); }
#search { width: 100%; background: var(--bg); border: 1px solid var(--input-border); color: var(--text); padding: 7px 10px; border-radius: 6px; font-size: 13px; outline: none; }
#search:focus { border-color: #4E79A7; }
#search-results { max-height: 140px; overflow-y: auto; padding: 4px 12px; border-bottom: 1px solid var(--border); display: none; }
.search-item { padding: 4px 6px; cursor: pointer; border-radius: 4px; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.search-item:hover { background: var(--border); }
#info-panel { padding: 14px; border-bottom: 1px solid var(--border); min-height: 140px; }
#info-panel h3 { font-size: 13px; color: var(--text-2); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.05em; }
#info-content { font-size: 13px; color: var(--text-3); line-height: 1.6; }
#info-content .field { margin-bottom: 5px; }
#info-content .field b { color: var(--text); }
#info-content .empty { color: var(--muted); font-style: italic; }
.neighbor-link { display: block; padding: 2px 6px; margin: 2px 0; border-radius: 3px; cursor: pointer; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-left: 3px solid var(--neighbor-border); }
.neighbor-link:hover { background: var(--border); }
#neighbors-list { max-height: 160px; overflow-y: auto; margin-top: 4px; }
#legend-wrap { flex: 1; overflow-y: auto; padding: 12px; }
#legend-wrap h3 { font-size: 13px; color: var(--text-2); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.05em; }
.legend-item { display: flex; align-items: center; gap: 8px; padding: 4px 0; cursor: pointer; border-radius: 4px; font-size: 12px; }
.legend-item:hover { background: var(--border); padding-left: 4px; }
.legend-item.dimmed { opacity: 0.35; }
.legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
.legend-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legend-count { color: var(--count); font-size: 11px; }
#stats { padding: 10px 14px; border-top: 1px solid var(--border); font-size: 11px; color: var(--muted); }
#legend-controls { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; padding: 4px 0; }
#legend-controls label { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px; color: var(--text-2); user-select: none; }
#legend-controls label:hover { color: var(--text); }
.legend-cb, #select-all-cb { appearance: none; -webkit-appearance: none; width: 14px; height: 14px; border: 1.5px solid var(--input-border); border-radius: 3px; background: var(--bg); cursor: pointer; position: relative; flex-shrink: 0; }
.legend-cb:checked, #select-all-cb:checked { background: #4E79A7; border-color: #4E79A7; }
.legend-cb:checked::after, #select-all-cb:checked::after { content: ''; position: absolute; left: 3.5px; top: 1px; width: 4px; height: 7px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
#select-all-cb:indeterminate { background: #4E79A7; border-color: #4E79A7; }
#select-all-cb:indeterminate::after { content: ''; position: absolute; left: 2px; top: 5px; width: 8px; height: 2px; background: #fff; border: none; transform: none; }
#theme-wrap { display: flex; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--border); }
#theme-wrap button { flex: 1; background: var(--bg); color: var(--text-2); border: 1px solid var(--input-border); border-radius: 4px; padding: 3px 0; font-size: 11px; cursor: pointer; }
#theme-wrap button:hover { color: var(--text); }
#theme-wrap button[aria-pressed="true"] { background: #4E79A7; border-color: #4E79A7; color: #fff; }
</style>
<script id="graphify-theme-init">
// Apply the saved theme before first paint (#3894). No saved choice keeps the
// historical dark look; "system" follows prefers-color-scheme.
(function () {
var pref = null;
try { pref = localStorage.getItem('graphify-theme'); } catch (e) {}
var t = pref === 'light' ? 'light'
: pref === 'system' && window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light'
: 'dark';
document.documentElement.setAttribute('data-theme', t);
})();
</script>
</head>
<body>
<div id="graph"></div>
<div id="sidebar">
<div id="theme-wrap" role="group" aria-label="Theme">
<button type="button" data-theme-choice="light">Light</button>
<button type="button" data-theme-choice="dark">Dark</button>
<button type="button" data-theme-choice="system">System</button>
</div>
<div id="search-wrap">
<input id="search" type="text" placeholder="Search nodes..." autocomplete="off">
<div id="search-results"></div>
</div>
<div id="info-panel">
<h3>Node Info</h3>
<div id="info-content"><span class="empty">Click a node to inspect it</span></div>
</div>
<div id="legend-wrap">
<h3>Communities</h3>
<div id="legend-controls">
<label><input type="checkbox" id="select-all-cb" checked onchange="toggleAllCommunities(!this.checked)">Select All</label>
</div>
<div id="legend"></div>
</div>
<div id="stats">132 nodes &middot; 189 edges &middot; 17 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "deploy", "label": "deploy.ps1", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "deploy.ps1", "community": 14, "community_name": "Deploy-Skript", "source_file": "deploy.ps1", "file_type": "code", "degree": 1}, {"id": "deploy_assert_ok", "label": "Assert-Ok()", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "Assert-Ok()", "community": 14, "community_name": "Deploy-Skript", "source_file": "deploy.ps1", "file_type": "code", "degree": 1}, {"id": "assets_js_site", "label": "site.js", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "site.js", "community": 15, "community_name": "Spotify Loader (site.js)", "source_file": "assets/js/site.js", "file_type": "code", "degree": 0}, {"id": "epk_build", "label": "build.ps1", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "build.ps1", "community": 16, "community_name": "EPK PDF Build", "source_file": "epk/build.ps1", "file_type": "code", "degree": 0}, {"id": "gitea_workflows_deploy", "label": "deploy.yml", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 14.7, "font": {"size": 12, "color": "#ffffff"}, "title": "deploy.yml", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 3}, {"id": "gitea_workflows_deploy_container_image", "label": "image", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "image", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 1}, {"id": "gitea_workflows_deploy_deploy_container", "label": "container", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 13.2, "font": {"size": 0, "color": "#ffffff"}, "title": "container", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 2}, {"id": "gitea_workflows_deploy_deploy_env", "label": "env", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 16.3, "font": {"size": 12, "color": "#ffffff"}, "title": "env", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 4}, {"id": "gitea_workflows_deploy_deploy_runs_on", "label": "runs-on", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "runs-on", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 1}, {"id": "gitea_workflows_deploy_deploy_steps", "label": "steps", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 16.3, "font": {"size": 12, "color": "#ffffff"}, "title": "steps", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 4}, {"id": "gitea_workflows_deploy_env_http_proxy", "label": "http_proxy", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "http_proxy", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 1}, {"id": "gitea_workflows_deploy_env_https_proxy", "label": "https_proxy", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "https_proxy", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file": ".gitea/workflows/deploy.yml", "file_type": "code", "degree": 1}, {"id": "gitea_workflows_deploy_env_no_proxy", "label": "no_proxy", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 11.6, "font": {"size": 0, "color": "#ffffff"}, "title": "no_proxy", "community": 2, "community_name": "Gitea Deploy Workflow", "source_file":Line truncated
const RAW_EDGES = [{"from": "deploy", "to": "deploy_assert_ok", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy", "to": "gitea_workflows_deploy_name", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy", "to": "gitea_workflows_deploy_on", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy", "to": "gitea_workflows_deploy_jobs", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_container", "to": "gitea_workflows_deploy_container_image", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_jobs_deploy", "to": "gitea_workflows_deploy_deploy_container", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_env", "to": "gitea_workflows_deploy_env_http_proxy", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_env", "to": "gitea_workflows_deploy_env_https_proxy", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_env", "to": "gitea_workflows_deploy_env_no_proxy", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_jobs_deploy", "to": "gitea_workflows_deploy_deploy_env", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_jobs_deploy", "to": "gitea_workflows_deploy_deploy_runs_on", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_steps", "to": "gitea_workflows_deploy_steps_uses", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_steps", "to": "gitea_workflows_deploy_steps_name", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_deploy_steps", "to": "gitea_workflows_deploy_steps_run", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_jobs_deploy", "to": "gitea_workflows_deploy_deploy_steps", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_jobs", "to": "gitea_workflows_deploy_jobs_deploy", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_on", "to": "gitea_workflows_deploy_on_push", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "gitea_workflows_deploy_on_push", "to": "gitea_workflows_deploy_push_branches", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "assets_css_main_design_tokens", "to": "assets_css_main", "label": "conceptually_related_to", "title": "conceptually_related_to [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "assets_css_main_flyer_wall", "to": "assets_css_main", "label": "conceptually_related_to", "title": "conceptually_related_to [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "layouts__default_baseof", "to": "assets_css_main", "label": "references", "title": "references [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "layouts_404", "to": "layouts__default_baseof", "label": "implements", "title": "implements [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "layouts__default_band", "to": "layouts_partials_img", "label": "calls", "title": "callsLine truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Templates &amp; Design", "count": 29}, {"cid": 1, "color": "#F28E2B", "label": "Band, EPK &amp; Regeln", "count": 27}, {"cid": 2, "color": "#E15759", "label": "Gitea Deploy Workflow", "count": 18}, {"cid": 3, "color": "#76B7B2", "label": "Datenschutz &amp; Impressum", "count": 9}, {"cid": 4, "color": "#59A14F", "label": "Show-Schema &amp; Mosel-Gigs", "count": 8}, {"cid": 5, "color": "#EDC948", "label": "Shows \u2194 EPK Sync", "count": 7}, {"cid": 6, "color": "#B07AA1", "label": "Pink Future &amp; Skatehalle", "count": 7}, {"cid": 7, "color": "#FF9DA7", "label": "Trierer Umland-Shows", "count": 7}, {"cid": 8, "color": "#9C755F", "label": "Rock im Gehege", "count": 4}, {"cid": 9, "color": "#BAB0AC", "label": "Tefftival", "count": 4}, {"cid": 10, "color": "#4E79A7", "label": "Album Release Party", "count": 2}, {"cid": 11, "color": "#F28E2B", "label": "Riez Kapellen-Contest", "count": 2}, {"cid": 12, "color": "#E15759", "label": "Altstadtfest Trier", "count": 2}, {"cid": 13, "color": "#76B7B2", "label": "Halloween Rock", "count": 2}, {"cid": 14, "color": "#59A14F", "label": "Deploy-Skript", "count": 2}, {"cid": 15, "color": "#EDC948", "label": "Spotify Loader (site.js)", "count": 1}, {"cid": 16, "color": "#B07AA1", "label": "EPK PDF Build", "count": 1}];
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');
}
// Build vis datasets
const nodesDS = new vis.DataSet(RAW_NODES.map((n, i) => ({
id: n.id, label: n.label, color: n.color, size: n.size,
font: n.font, title: n.title,
// Fermat/golden-angle spiral seed positions (#3699): spreading nodes out
// before physics runs keeps avoidOverlap from computing near-zero-distance
// repulsion that blows the BarnesHut recursion into a stack overflow on large
// graphs. `i` is the map index — physics still settles small graphs identically.
x: 30 * Math.sqrt(i) * Math.cos(i * 2.4),
y: 30 * Math.sqrt(i) * Math.sin(i * 2.4),
community: n.community, community_name: n.community_name,
source_file: n.source_file, file_type: n.file_type, degree: n.degree,
member_count: n.member_count,
})));
const edgesDS = new vis.DataSet(RAW_EDGES.map((e, i) => ({
id: i, from: e.from, to: e.to,
label: '',
title: e.title,
dashes: e.dashes,
width: e.width,
color: e.color,
arrows: { to: { enabled: true, scaleFactor: 0.5 } },
})));
const container = document.getElementById('graph');
const network = new vis.Network(container, { nodes: nodesDS, edges: edgesDS }, {
physics: {
enabled: true,
solver: 'forceAtlas2Based',
forceAtlas2Based: {
gravitationalConstant: -60,
centralGravity: 0.005,
springLength: 120,
springConstant: 0.08,
damping: 0.4,
avoidOverlap: 0.8,
},
stabilization: { iterations: 200, fit: true },
},
interaction: {
hover: true,
tooltipDelay: 100,
hideEdgesOnDrag: true,
navigationButtons: false,
keyboard: false,
},
nodes: { shape: 'dot', borderWidth: 1.5 },
edges: { smooth: { type: 'continuous', roundness: 0.2 }, selectionWidth: 3 },
});
// Theme toggle (#3894): Light / Dark / System, persisted in localStorage.
const THEME_KEY = 'graphify-theme';
const themeMQ = window.matchMedia ? window.matchMedia('(prefers-color-scheme: light)') : null;
let themeLabelColor = '#ffffff'; // matches the per-node font color set in Python
function themePref() {
let p = null;
try { p = localStorage.getItem(THEME_KEY); } catch (e) {}
return (p === 'light' || p === 'dark' || p === 'system') ? p : null;
}
function applyTheme(pref) {
const t = pref === 'light' ? 'light' : (pref === 'system' && themeMQ && themeMQ.matches) ? 'light' : 'dark';
const root = document.documentElement;
if (!root) return;
root.setAttribute('data-theme', t);
document.querySelectorAll('[data-theme-choice]').forEach(b => {
b.setAttribute('aria-pressed', String(b.dataset.themeChoice === (pref || 'dark')));
});
const labelColor = getComputedStyle(root).getPropertyValue('--node-label').trim();
if (labelColor && labelColor !== themeLabelColor) {
themeLabelColor = labelColor;
nodesDS.update(nodesDS.get().map(n => ({ id: n.id, font: Object.assign({}, n.font, { color: labelColor }) })));
}
}
document.querySelectorAll('[data-theme-choice]').forEach(b => {
b.addEventListener('click', () => {
const pref = b.dataset.themeChoice;
try { localStorage.setItem(THEME_KEY, pref); } catch (e) {}
applyTheme(pref);
});
});
if (themeMQ) {
const onSchemeChange = () => { if (themePref() === 'system') applyTheme('system'); };
if (themeMQ.addEventListener) themeMQ.addEventListener('change', onSchemeChange);
else if (themeMQ.addListener) themeMQ.addListener(onSchemeChange);
}
applyTheme(themePref());
network.once('stabilizationIterationsDone', () => {
network.setOptions({ physics: { enabled: false } });
});
function showInfo(nodeId) {
const n = nodesDS.get(nodeId);
if (!n) return;
const neighborIds = network.getConnectedNodes(nodeId);
const neighborItems = neighborIds.map(nid => {
const nb = nodesDS.get(nid);
const color = nb ? nb.color.background : '#555';
return `<span class="neighbor-link" style="border-left-color:${esc(color)}" data-nid="${esc(nid)}">${esc(nb ? nb.label : nid)}</span>`;
}).join('');
const isMetaNode = !n.file_type && !n.source_file;
let html = `<div class="field"><b>${esc(n.label)}</b></div>`;
if (!isMetaNode) {
html += `<div class="field">Type: ${esc(n.file_type || 'unknown')}</div>`;
}
html += `<div class="field">Community: ${esc(n.community_name || '')}</div>`;
if (!isMetaNode) {
html += `<div class="field">Source: ${esc(n.source_file || '-')}</div>`;
} else if (n.member_count !== undefined && n.member_count !== null) {
html += `<div class="field">Members: ${esc(n.member_count)}</div>`;
}
html += `<div class="field">Degree: ${n.degree}</div>`;
if (neighborIds.length) {
html += `<div class="field" style="margin-top:8px;color:var(--text-2);font-size:11px">Neighbors (${neighborIds.length})</div><div id="neighbors-list">${neighborItems}</div>`;
}
document.getElementById('info-content').innerHTML = html;
}
function focusNode(nodeId) {
network.focus(nodeId, { scale: 1.4, animation: true });
network.selectNodes([nodeId]);
showInfo(nodeId);
}
// Neighbor links use a data attribute + one delegated listener rather than an
// inline onclick. A node id/label sourced from a document or a scraped URL
// (graphify add) can contain a double-quote; dropping the stringified id
// unescaped into a quoted onclick both broke every link and allowed a hostile
// source to inject an event handler into the local report (stored XSS, #1838).
// esc() on data-nid keeps the value inside the attribute; the listener reads it
// back verbatim. Bound to document so it survives the innerHTML rebuild that
// recreates #neighbors-list on each showInfo().
document.addEventListener('click', e => {
const el = e.target.closest('.neighbor-link');
if (el && el.dataset.nid !== undefined) focusNode(el.dataset.nid);
});
// Sidebar tooltips reuse vis-network's .vis-tooltip style and 100ms tooltipDelay.
// Names get one only when CSS ellipsis truncates them (the full text is still in
// the DOM); counts always get one, to say what the number is. Text is set with
// textContent only (labels are untrusted). Delegated on document so rows rebuilt
// later (search results, showInfo()) are covered.
const sidebarTip = document.createElement('div');
sidebarTip.className = 'vis-tooltip';
sidebarTip.style.cssText = 'white-space: normal; max-width: 360px; overflow-wrap: break-word;';
document.body.appendChild(sidebarTip);
let sidebarTipTimer = null;
let sidebarTipEl = null; // element whose text the tooltip shows
let sidebarTipZone = null; // element the pointer must leave to hide it
function hideSidebarTip() {
clearTimeout(sidebarTipTimer);
sidebarTip.style.visibility = 'hidden';
sidebarTip.textContent = '';
sidebarTipEl = sidebarTipZone = null;
}
document.addEventListener('mouseover', e => {
const zone = e.target.closest && e.target.closest('.legend-count, .legend-item, .search-item, .neighbor-link');
// Anywhere on a legend row except its count (dot, checkbox, gaps, padding)
// stands for the row's name, so moving within the row never re-triggers it.
const el = zone && zone.classList.contains('legend-item') ? zone.querySelector('.legend-label') : zone;
if (!el || el === sidebarTipEl) return;
hideSidebarTip();
const isCount = el.classList.contains('legend-count');
if (!isCount && el.scrollWidth <= el.clientWidth) return;
const text = isCount ? `${el.textContent} ${el.textContent === '1' ? 'node' : 'nodes'}` : el.textContent;
sidebarTipEl = el;
sidebarTipZone = zone;
const x = e.clientX, y = e.clientY;
sidebarTipTimer = setTimeout(() => {
sidebarTip.textContent = text;
sidebarTip.style.left = sidebarTip.style.top = '0px'; // measure at full max-width
sidebarTip.style.visibility = 'visible';
const w = sidebarTip.offsetWidth, h = sidebarTip.offsetHeight;
sidebarTip.style.left = Math.max(4, Math.min(x + 12, window.innerWidth - w - 4)) + 'px';
sidebarTip.style.top = (y + 16 + h > window.innerHeight ? Math.max(4, y - h - 8) : y + 16) + 'px';
}, 100);
});
document.addEventListener('mouseout', e => {
if (sidebarTipZone && !sidebarTipZone.contains(e.relatedTarget)) hideSidebarTip();
});
// A click rebuilds or hides the row (showInfo(), search pick) without a mouseout.
document.addEventListener('mousedown', hideSidebarTip);
// Track hovered node — hover detection is more reliable than click params
let hoveredNodeId = null;
network.on('hoverNode', params => {
hoveredNodeId = params.node;
container.style.cursor = 'pointer';
});
network.on('blurNode', () => {
hoveredNodeId = null;
container.style.cursor = 'default';
});
container.addEventListener('click', () => {
if (hoveredNodeId !== null) {
showInfo(hoveredNodeId);
network.selectNodes([hoveredNodeId]);
}
});
network.on('click', params => {
if (params.nodes.length > 0) {
showInfo(params.nodes[0]);
} else if (hoveredNodeId === null) {
document.getElementById('info-content').innerHTML = '<span class="empty">Click a node to inspect it</span>';
}
});
const searchInput = document.getElementById('search');
const searchResults = document.getElementById('search-results');
searchInput.addEventListener('input', () => {
const q = searchInput.value.toLowerCase().trim();
searchResults.innerHTML = '';
if (!q) { searchResults.style.display = 'none'; return; }
const matches = RAW_NODES.filter(n => n.label.toLowerCase().includes(q)).slice(0, 20);
if (!matches.length) { searchResults.style.display = 'none'; return; }
searchResults.style.display = 'block';
matches.forEach(n => {
const el = document.createElement('div');
el.className = 'search-item';
el.textContent = n.label;
el.style.borderLeft = `3px solid ${n.color.background}`;
el.style.paddingLeft = '8px';
el.onclick = () => {
network.focus(n.id, { scale: 1.5, animation: true });
network.selectNodes([n.id]);
showInfo(n.id);
searchResults.style.display = 'none';
searchInput.value = '';
};
searchResults.appendChild(el);
});
});
document.addEventListener('click', e => {
if (!searchResults.contains(e.target) && e.target !== searchInput)
searchResults.style.display = 'none';
});
const hiddenCommunities = new Set();
const selectAllCb = document.getElementById('select-all-cb');
function updateSelectAllState() {
const total = LEGEND.length;
const hidden = hiddenCommunities.size;
selectAllCb.checked = hidden === 0;
selectAllCb.indeterminate = hidden > 0 && hidden < total;
}
function toggleAllCommunities(hide) {
document.querySelectorAll('.legend-item').forEach(item => {
hide ? item.classList.add('dimmed') : item.classList.remove('dimmed');
});
document.querySelectorAll('.legend-cb').forEach(cb => {
cb.checked = !hide;
});
LEGEND.forEach(c => {
if (hide) hiddenCommunities.add(c.cid); else hiddenCommunities.delete(c.cid);
});
const updates = RAW_NODES.map(n => ({ id: n.id, hidden: hide }));
nodesDS.update(updates);
updateSelectAllState();
}
const legendEl = document.getElementById('legend');
LEGEND.forEach(c => {
const item = document.createElement('div');
item.className = 'legend-item';
const cb = document.createElement('input');
cb.type = 'checkbox';
cb.className = 'legend-cb';
cb.checked = true;
cb.addEventListener('change', (e) => {
e.stopPropagation();
if (cb.checked) {
hiddenCommunities.delete(c.cid);
item.classList.remove('dimmed');
} else {
hiddenCommunities.add(c.cid);
item.classList.add('dimmed');
}
const updates = RAW_NODES
.filter(n => n.community === c.cid)
.map(n => ({ id: n.id, hidden: !cb.checked }));
nodesDS.update(updates);
updateSelectAllState();
});
item.innerHTML = `<div class="legend-dot" style="background:${c.color}"></div>
<span class="legend-label">${c.label}</span>
<span class="legend-count">${c.count}</span>`;
item.prepend(cb);
item.onclick = (e) => {
if (e.target === cb) return;
cb.checked = !cb.checked;
cb.dispatchEvent(new Event('change'));
};
legendEl.appendChild(item);
});
</script>
<script>
// Render hyperedges as shaded regions
const hyperedges = [{"id": "epk_four_page_layout", "label": "EPK four A4 pages", "nodes": ["epk_epk_cover_page", "epk_epk_bio_page", "epk_epk_band_music_page", "epk_epk_live_contact_page"], "relation": "form", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "epk/epk.html"}, {"id": "release_data_pipeline", "label": "Release cover filename parsing feeding music page and album schema", "nodes": ["layouts_partials_releases", "layouts_partials_releases_filename_convention", "layouts_music_list", "layouts_partials_schema_musicgroup"], "relation": "form", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "layouts/partials/releases.html"}, {"id": "privacy_by_design_choices", "label": "Privacy-conscious site choices (local fonts, click-to-load Spotify, DSGVO)", "nodes": ["content_datenschutz_local_fonts", "content_datenschutz_spotify_click_to_load", "content_datenschutz_dsgvo_rights", "content_datenschutz_hosting_1blu"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/Datenschutz.md"}, {"id": "seo_layer", "label": "SEO layer (meta tags, JSON-LD, robots, show redirects)", "nodes": ["layouts__default_baseof_seo_meta", "layouts_partials_schema", "layouts_robots", "layouts_shows_single"], "relation": "form", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "layouts/_default/baseof.html"}, {"id": "trier_city_shows", "label": "Shows in the city of Trier", "nodes": ["content_shows_2022_jukufe_light_show", "content_shows_2023_pink_future_show", "content_shows_2024_pink_future_show", "content_shows_2025_album_release_party_show", "content_shows_2026_altstadtfest_trier_show", "content_shows_2026_luke_show"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/shows/_index.md"}, {"id": "upcoming_shows_2026", "label": "Upcoming shows after 2026-10-30 (EPK 'N\u00e4chste Shows')", "nodes": ["content_shows_2026_halloween_show", "content_shows_2026_tefftival_show", "content_shows__index_shows"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "content/shows/_index.md"}, {"id": "epk_website_manual_sync_flow", "label": "Website content manually mirrored into EPK", "nodes": ["claude_epk_manual_sync", "content__index_band_bio", "content_about_members", "content_music__index_music_page", "epk_epk_document"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "CLAUDE.md"}, {"id": "show_rendering_flow", "label": "Show listing rendering (home, shows page, card, JSON-LD events)", "nodes": ["layouts_index", "layouts_shows_list", "layouts_partials_show_card", "layouts_partials_schema_musicevent"], "relation": "participate_in", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "layouts/shows/list.html"}];
// afterDrawing passes ctx already transformed to network coordinate space.
// Draw node positions raw — no manual pan/zoom/DPR math needed.
// Andrew's monotone chain. Returns the hull in counter-clockwise order, which
// is what the perimeter must be traced in. Collinear and duplicate points
// collapse to the extremes, so degenerate member sets render as a segment
// rather than a zero-area crossed path.
function convexHull(pts) {
const p = pts.slice().sort((a, b) => (a.x - b.x) || (a.y - b.y));
if (p.length < 3) return p;
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
const build = seq => {
const out = [];
for (const q of seq) {
while (out.length >= 2 && cross(out[out.length - 2], out[out.length - 1], q) <= 0) out.pop();
out.push(q);
}
out.pop();
return out;
};
const hull = build(p).concat(build(p.slice().reverse()));
return hull.length >= 3 ? hull : p;
}
network.on('afterDrawing', function(ctx) {
hyperedges.forEach(h => {
const positions = h.nodes
.map(nid => network.getPositions([nid])[nid])
.filter(p => p !== undefined);
if (positions.length < 2) return;
ctx.save();
ctx.globalAlpha = 0.12;
ctx.fillStyle = '#6366f1';
ctx.strokeStyle = '#6366f1';
ctx.lineWidth = 2;
ctx.beginPath();
// Centroid and expanded hull in network coordinates.
// The perimeter must follow hull order, not h.nodes order: tracing the
// raw member order self-intersects whenever the layout does not happen
// to place members in angular order, filling as crossed wedges.
const cx = positions.reduce((s, p) => s + p.x, 0) / positions.length;
const cy = positions.reduce((s, p) => s + p.y, 0) / positions.length;
const hull = convexHull(positions);
const expanded = hull.map(p => ({
x: cx + (p.x - cx) * 1.15,
y: cy + (p.y - cy) * 1.15
}));
ctx.moveTo(expanded[0].x, expanded[0].y);
expanded.slice(1).forEach(p => ctx.lineTo(p.x, p.y));
ctx.closePath();
ctx.fill();
ctx.globalAlpha = 0.4;
ctx.stroke();
// Label
ctx.globalAlpha = 0.8;
ctx.fillStyle = '#4f46e5';
ctx.font = 'bold 11px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(h.label, cx, cy - 5);
ctx.restore();
});
});
</script>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
{"directed":false,"multigraph":false,"graph":{"hyperedges":[{"id":"epk_four_page_layout","label":"EPK four A4 pages","nodes":["epk_epk_cover_page","epk_epk_bio_page","epk_epk_band_music_page","epk_epk_live_contact_page"],"relation":"form","confidence":"EXTRACTED","confidence_score":1.0,"source_file":"epk/epk.html"},{"id":"release_data_pipeline","label":"Release cover filename parsing feeding music page and album schema","nodes":["layouts_partials_releases","layouts_partials_releases_filename_convention","layouts_music_list","layouts_partials_schema_musicgroup"],"relation":"form","confidence":"EXTRACTED","confidence_score":1.0,"source_file":"layouts/partials/releases.html"},{"id":"privacy_by_design_choices","label":"Privacy-conscious site choices (local fonts, click-to-load Spotify, DSGVO)","nodes":["content_datenschutz_local_fonts","content_datenschutz_spotify_click_to_load","content_datenschutz_dsgvo_rights","content_datenschutz_hosting_1blu"],"relation":"participate_in","confidence":"INFERRED","confidence_score":0.75,"source_file":"content/Datenschutz.md"},{"id":"seo_layer","label":"SEO layer (meta tags, JSON-LD, robots, show redirects)","nodes":["layouts__default_baseof_seo_meta","layouts_partials_schema","layouts_robots","layouts_shows_single"],"relation":"form","confidence":"INFERRED","confidence_score":0.75,"source_file":"layouts/_default/baseof.html"},{"id":"trier_city_shows","label":"Shows in the city of Trier","nodes":["content_shows_2022_jukufe_light_show","content_shows_2023_pink_future_show","content_shows_2024_pink_future_show","content_shows_2025_album_release_party_show","content_shows_2026_altstadtfest_trier_show","content_shows_2026_luke_show"],"relation":"participate_in","confidence":"INFERRED","confidence_score":0.75,"source_file":"content/shows/_index.md"},{"id":"upcoming_shows_2026","label":"Upcoming shows after 2026-10-30 (EPK 'N\u00e4chste Shows')","nodes":["content_shows_2026_halloween_show","content_shows_2026_tefftival_show","content_shows__index_shows"],"relation":"participate_in","confidence":"INFERRED","confidence_score":0.75,"source_file":"content/shows/_index.md"},{"id":"epk_website_manual_sync_flow","label":"Website content manually mirrored into EPK","nodes":["claude_epk_manual_sync","content__index_band_bio","content_about_members","content_music__index_music_page","epk_epk_document"],"relation":"participate_in","confidence":"INFERRED","confidence_score":0.85,"source_file":"CLAUDE.md"},{"id":"show_rendering_flow","label":"Show listing rendering (home, shows page, card, JSON-LD events)","nodes":["layouts_index","layouts_shows_list","layouts_partials_show_card","layouts_partials_schema_musicevent"],"relation":"participate_in","confidence":"INFERRED","confidence_score":0.85,"source_file":"layouts/shows/list.html"}],"schema_version":1,"graphify_version":"0.9.97"},"nodes":[{"id":"deploy","label":"deploy.ps1","_origin":"ast","community":14,"community_name":"Deploy-Skript","file_type":"code","norm_label":"deploy.ps1","source_file":"deploy.ps1","source_location":"L1"},{"id":"deploy_assert_ok","label":"Assert-Ok()","_origin":"ast","community":14,"community_name":"Deploy-Skript","file_type":"code","norm_label":"assert-ok()","source_file":"deploy.ps1","source_location":"L21"},{"id":"assets_js_site","label":"site.js","_origin":"ast","community":15,"community_name":"Spotify Loader (site.js)","file_type":"code","norm_label":"site.js","source_file":"assets/js/site.js","source_location":"L1"},{"id":"epk_build","label":"build.ps1","_origin":"ast","community":16,"community_name":"EPK PDF Build","file_type":"code","norm_label":"build.ps1","source_file":"epk/build.ps1","source_location":"L1"},{"id":"gitea_workflows_deploy","label":"deploy.yml","_origin":"ast","community":2,"community_name":"Gitea Deploy Workflow","file_type":"code","norm_label":"deploy.yml","source_file":".gitea/workflows/deploy.yml","source_location":"L1"},{"id":"gitea_workflows_deploy_container_image","label":"image","_origin":"ast","community":2,"community_name":"Gitea Deploy Workflow","file_type":"code","norm_label":"image","source_file":".gitea/workflows/deploy.yml","source_location":"L12"},{"id":"gitea_workflows_deploy_deploy_container","label":"container","_origin":"ast","community":2,"community_name":"Gitea Deploy Workflow","file_type":"code","norm_label":"container","source_file":".gitea/workflows/deploy.yml","source_location":"L11"},{"id":"gitea_workflows_deploy_deploy_env","label":"env","_origin":"ast","community":2,"community_name":"Gitea Deploy Workflow","file_type":"code","norm_label":"env","source_file":".gitea/workflows/deploy.yml","source_location":"L14"},{"id":"gitea_workflows_deploy_deploy_runs_on","label":"runs-on","_origin":"ast","community":2,"community_name":"Gitea Deploy Workflow","file_type":"code","norm_label":"runs-on","source_file":".gitea/workflows/deploy.yml","source_location":"L10"},{"id":"gitea_workflows_deploy_deploy_steps","label":"steps","_origin":"ast","community":2,"community_name":"Gitea Line truncated
+284
View File
@@ -0,0 +1,284 @@
{
".gitea/workflows/deploy.yml": {
"mtime": 1792436508.1113694,
"seen": 1793375630.6811461,
"ast_hash": "586da739996d36d4573e9010c336b8f5",
"semantic_hash": "586da739996d36d4573e9010c336b8f5"
},
"assets/js/site.js": {
"mtime": 1792428051.347229,
"seen": 1793375630.6811461,
"ast_hash": "4f3a97a77436926df1e0ffb8b7bd9433",
"semantic_hash": "4f3a97a77436926df1e0ffb8b7bd9433"
},
"deploy.ps1": {
"mtime": 1792439721.9094982,
"seen": 1793375630.6811461,
"ast_hash": "9769be30a5e3fac69615581a1d7766ac",
"semantic_hash": "9769be30a5e3fac69615581a1d7766ac"
},
"epk/build.ps1": {
"mtime": 1792441385.0702047,
"seen": 1793375630.6811461,
"ast_hash": "5f39994f7595891549f59732569f3b55",
"semantic_hash": "5f39994f7595891549f59732569f3b55"
},
"CLAUDE.md": {
"mtime": 1793374882.1850684,
"seen": 1793375630.6811461,
"ast_hash": "bbcfa8bc7030d36d30c5d965107fdfb0",
"semantic_hash": "bbcfa8bc7030d36d30c5d965107fdfb0"
},
"archetypes/default.md": {
"mtime": 1779119062.703552,
"seen": 1793375630.6811461,
"ast_hash": "89064672db31fdc98e72345241a0919f",
"semantic_hash": "89064672db31fdc98e72345241a0919f"
},
"content/Datenschutz.md": {
"mtime": 1792427965.1255074,
"seen": 1793375630.6811461,
"ast_hash": "801aa0befa8fe48c86f3d54a5e324877",
"semantic_hash": "801aa0befa8fe48c86f3d54a5e324877"
},
"content/Impressum.md": {
"mtime": 1792427965.124507,
"seen": 1793375630.6811461,
"ast_hash": "e448a039e0697a57a78069955c0cbcde",
"semantic_hash": "e448a039e0697a57a78069955c0cbcde"
},
"content/_index.md": {
"mtime": 1792427946.806149,
"seen": 1793375630.6811461,
"ast_hash": "cf0e83830cf2373f514c11e4575e9a71",
"semantic_hash": "cf0e83830cf2373f514c11e4575e9a71"
},
"content/about.md": {
"mtime": 1792438093.6905713,
"seen": 1793375630.6811461,
"ast_hash": "c887d819271e6e5590377e00d8ed482f",
"semantic_hash": "c887d819271e6e5590377e00d8ed482f"
},
"content/music/_index.md": {
"mtime": 1792437673.2972002,
"seen": 1793375630.6811461,
"ast_hash": "e27d2ca6914d7e2d24449869fc1fc29d",
"semantic_hash": "e27d2ca6914d7e2d24449869fc1fc29d"
},
"content/shows/2022_Jukufe_light.md": {
"mtime": 1779119062.7066143,
"seen": 1793375630.6811461,
"ast_hash": "dbb9bf801e33d4cf46cc6be783cd5ecd",
"semantic_hash": "dbb9bf801e33d4cf46cc6be783cd5ecd"
},
"content/shows/2022_Konz_wird_laut.md": {
"mtime": 1779119062.7076137,
"seen": 1793375630.6811461,
"ast_hash": "66a008810041f547f43964884c208b37",
"semantic_hash": "66a008810041f547f43964884c208b37"
},
"content/shows/2022_Rock_im_Gehege.md": {
"mtime": 1779119062.7076137,
"seen": 1793375630.6811461,
"ast_hash": "c9be2cb8d0e08720a17360a68079697b",
"semantic_hash": "c9be2cb8d0e08720a17360a68079697b"
},
"content/shows/2022_Tefftival.md": {
"mtime": 1779119062.7076137,
"seen": 1793375630.6811461,
"ast_hash": "40a646f2a9950463cea4a4c1db072d52",
"semantic_hash": "40a646f2a9950463cea4a4c1db072d52"
},
"content/shows/2023_Moselrock.md": {
"mtime": 1779119062.7076137,
"seen": 1793375630.6811461,
"ast_hash": "e1cac874ba92686c9e93b69ff8f25ca2",
"semantic_hash": "e1cac874ba92686c9e93b69ff8f25ca2"
},
"content/shows/2023_Pink_Future.md": {
"mtime": 1792427947.035097,
"seen": 1793375630.6811461,
"ast_hash": "6c069f3c0905199fc71964302788a3b2",
"semantic_hash": "6c069f3c0905199fc71964302788a3b2"
},
"content/shows/2024_Pink_Future.md": {
"mtime": 1793374815.6689198,
"seen": 1793375630.6811461,
"ast_hash": "6c7dffee2a8ddef3aab20046a31dfcab",
"semantic_hash": "6c7dffee2a8ddef3aab20046a31dfcab"
},
"content/shows/2024_Rock_fuer_Ruanda.md": {
"mtime": 1779119062.7086136,
"seen": 1793375630.6811461,
"ast_hash": "61ad5d561e4baeb73f98c92c5bda5132",
"semantic_hash": "61ad5d561e4baeb73f98c92c5bda5132"
},
"content/shows/2024_Rock_im_Gehege.md": {
"mtime": 1779119062.7086136,
"seen": 1793375630.6811461,
"ast_hash": "921ef9bb8cd31bf013d49fa5cf67b52b",
"semantic_hash": "921ef9bb8cd31bf013d49fa5cf67b52b"
},
"content/shows/2025_Album_Release_Party.md": {
"mtime": 1792435816.801632,
"seen": 1793375630.6811461,
"ast_hash": "19b2a4e1d791a749fd96ed92563c9a13",
"semantic_hash": "19b2a4e1d791a749fd96ed92563c9a13"
},
"content/shows/2025_Bullenhitze.md": {
"mtime": 1792436153.8206096,
"seen": 1793375630.6811461,
"ast_hash": "964b3ad0b776203d5c132eb4890e9237",
"semantic_hash": "964b3ad0b776203d5c132eb4890e9237"
},
"content/shows/2025_Riez_Kapellenkontest.md": {
"mtime": 1792427947.085265,
"seen": 1793375630.6811461,
"ast_hash": "ba49c824c77a5834bced087e1ef8b8a2",
"semantic_hash": "ba49c824c77a5834bced087e1ef8b8a2"
},
"content/shows/2026_Altstadtfest_Trier.md": {
"mtime": 1792435301.8733604,
"seen": 1793375630.6811461,
"ast_hash": "2a2ab6188c4f100a95f948550b3d67c1",
"semantic_hash": "2a2ab6188c4f100a95f948550b3d67c1"
},
"content/shows/2026_Halloween.md": {
"mtime": 1793374815.6498969,
"seen": 1793375630.6811461,
"ast_hash": "6c36d994220091f6db37298850d931cf",
"semantic_hash": "6c36d994220091f6db37298850d931cf"
},
"content/shows/2026_Highway_to_Kell.md": {
"mtime": 1792436187.7946775,
"seen": 1793375630.6811461,
"ast_hash": "95e1272d92c319bf6338192bf3bce62b",
"semantic_hash": "95e1272d92c319bf6338192bf3bce62b"
},
"content/shows/2026_Luke.md": {
"mtime": 1792435449.494565,
"seen": 1793375630.6811461,
"ast_hash": "8958c7f15452cb736d5f6df3fddfc379",
"semantic_hash": "8958c7f15452cb736d5f6df3fddfc379"
},
"content/shows/2026_Tefftival.md": {
"mtime": 1792436877.4647188,
"seen": 1793375630.6811461,
"ast_hash": "0adc06b7718f73fa8e60eec7be5a53af",
"semantic_hash": "0adc06b7718f73fa8e60eec7be5a53af"
},
"content/shows/_index.md": {
"mtime": 1792428085.075345,
"seen": 1793375630.6811461,
"ast_hash": "eb937e61fa9a192bf7a90293ee41740e",
"semantic_hash": "eb937e61fa9a192bf7a90293ee41740e"
},
"epk/epk.html": {
"mtime": 1792441190.7920048,
"seen": 1793375630.6811461,
"ast_hash": "18c65a3c8fbaf6d00789168918336eec",
"semantic_hash": "18c65a3c8fbaf6d00789168918336eec"
},
"layouts/404.html": {
"mtime": 1792427930.2489362,
"seen": 1793375630.6811461,
"ast_hash": "737e308941ae0919e20f2df5af3506cb",
"semantic_hash": "737e308941ae0919e20f2df5af3506cb"
},
"layouts/_default/band.html": {
"mtime": 1792438116.8336325,
"seen": 1793375630.6811461,
"ast_hash": "7360a1b4ec02791fbfdb3ea7ce702d5a",
"semantic_hash": "7360a1b4ec02791fbfdb3ea7ce702d5a"
},
"layouts/_default/baseof.html": {
"mtime": 1793374865.1657135,
"seen": 1793375630.6811461,
"ast_hash": "60f2a1a9fb6bb0e66e58dc37032992a3",
"semantic_hash": "60f2a1a9fb6bb0e66e58dc37032992a3"
},
"layouts/_default/list.html": {
"mtime": 1792427929.1876495,
"seen": 1793375630.6811461,
"ast_hash": "0ceee9c1e524868aceb3cfa02d0505e5",
"semantic_hash": "0ceee9c1e524868aceb3cfa02d0505e5"
},
"layouts/_default/single.html": {
"mtime": 1792427928.103781,
"seen": 1793375630.6811461,
"ast_hash": "9e1860e9098202d2737db3f543b99f1f",
"semantic_hash": "9e1860e9098202d2737db3f543b99f1f"
},
"layouts/index.html": {
"mtime": 1792436553.057485,
"seen": 1793375630.6811461,
"ast_hash": "36cbbdf1d3a2e88d9722fb0fc1458617",
"semantic_hash": "36cbbdf1d3a2e88d9722fb0fc1458617"
},
"layouts/music/list.html": {
"mtime": 1792437676.4604757,
"seen": 1793375630.6811461,
"ast_hash": "27d3bbdcb8a26508116f91c3f0e71c88",
"semantic_hash": "27d3bbdcb8a26508116f91c3f0e71c88"
},
"layouts/partials/footer.html": {
"mtime": 1792438077.2061362,
"seen": 1793375630.6811461,
"ast_hash": "041f2f4ba559ce00354c0f6ca5c324c7",
"semantic_hash": "041f2f4ba559ce00354c0f6ca5c324c7"
},
"layouts/partials/header.html": {
"mtime": 1792427957.2606187,
"seen": 1793375630.6811461,
"ast_hash": "cc60cdb7274d2f241a66aef491fd4af0",
"semantic_hash": "cc60cdb7274d2f241a66aef491fd4af0"
},
"layouts/partials/img.html": {
"mtime": 1792437654.353445,
"seen": 1793375630.6811461,
"ast_hash": "fc397069f2f4fa9249ee959f7694a63e",
"semantic_hash": "fc397069f2f4fa9249ee959f7694a63e"
},
"layouts/partials/releases.html": {
"mtime": 1792437655.4155233,
"seen": 1793375630.6811461,
"ast_hash": "de1660688b6b38926d53e9674c13f211",
"semantic_hash": "de1660688b6b38926d53e9674c13f211"
},
"layouts/partials/schema.html": {
"mtime": 1793374856.2443554,
"seen": 1793375630.6811461,
"ast_hash": "042c009492de79ef01b59e488d23afbe",
"semantic_hash": "042c009492de79ef01b59e488d23afbe"
},
"layouts/partials/show-card.html": {
"mtime": 1792436684.4066665,
"seen": 1793375630.6811461,
"ast_hash": "59cf866d687ab013af16144c672c5731",
"semantic_hash": "59cf866d687ab013af16144c672c5731"
},
"layouts/partials/spotify.html": {
"mtime": 1792427891.8614888,
"seen": 1793375630.6811461,
"ast_hash": "37aa573154e707ff7af871d1bde6fe60",
"semantic_hash": "37aa573154e707ff7af871d1bde6fe60"
},
"layouts/robots.txt": {
"mtime": 1793374831.4034257,
"seen": 1793375630.6811461,
"ast_hash": "73658f017f7da8ee2d3098e78d9806d5",
"semantic_hash": "73658f017f7da8ee2d3098e78d9806d5"
},
"layouts/shows/list.html": {
"mtime": 1792427924.881836,
"seen": 1793375630.6811461,
"ast_hash": "d606aa8ca7c0152b8baab7a35e592757",
"semantic_hash": "d606aa8ca7c0152b8baab7a35e592757"
},
"layouts/shows/single.html": {
"mtime": 1792428085.1042292,
"seen": 1793375630.6811461,
"ast_hash": "9fb7cc1072114103cead8f7250e99ce8",
"semantic_hash": "9fb7cc1072114103cead8f7250e99ce8"
}
}
+11
View File
@@ -3,6 +3,9 @@ baseURL = "https://www.deepwatersurvival.de/"
languageCode = "de" languageCode = "de"
defaultContentLanguage = "de" defaultContentLanguage = "de"
disableKinds = ["taxonomy", "term", "RSS"] disableKinds = ["taxonomy", "term", "RSS"]
enableRobotsTXT = true
# Shows liegen in der Zukunft – ohne diese Option würde Hugo sie nicht bauen.
buildFuture = true
[params] [params]
description = "Deepwater Survival – Punkrock aus Trier. Debütalbum „Ocean Tales“ jetzt überall, wo es Musik gibt." description = "Deepwater Survival – Punkrock aus Trier. Debütalbum „Ocean Tales“ jetzt überall, wo es Musik gibt."
@@ -11,6 +14,10 @@ disableKinds = ["taxonomy", "term", "RSS"]
spotifyEmbed = "https://open.spotify.com/embed/artist/2TQ9HNBTNCmUthpg9ippHs?utm_source=generator&theme=0" spotifyEmbed = "https://open.spotify.com/embed/artist/2TQ9HNBTNCmUthpg9ippHs?utm_source=generator&theme=0"
instagram = "https://www.instagram.com/deepwatersurvival/" instagram = "https://www.instagram.com/deepwatersurvival/"
youtube = "https://www.youtube.com/@deepwatersurvival730" youtube = "https://www.youtube.com/@deepwatersurvival730"
[params.photographer]
name = "Lukas Ittenbach"
handle = "shot__itt"
instagram = "https://www.instagram.com/shot__itt/"
[[menu.main]] [[menu.main]]
name = "Home" name = "Home"
@@ -47,3 +54,7 @@ disableKinds = ["taxonomy", "term", "RSS"]
[[module.mounts]] [[module.mounts]]
source = "assets" source = "assets"
target = "assets" target = "assets"
# Release-Cover: Dateiname = [JJJJMMTT]_[Single|Album]_[Name].jpg
[[module.mounts]]
source = "releases"
target = "assets/img/releases"
+22
View File
@@ -23,4 +23,26 @@
{{ partial "img.html" (dict "src" . "alt" "Gruppenfoto von Deepwater Survival im Backstage-Flur" "sizes" "100vw" "widths" (slice 800 1400 2000)) }} {{ partial "img.html" (dict "src" . "alt" "Gruppenfoto von Deepwater Survival im Backstage-Flur" "sizes" "100vw" "widths" (slice 800 1400 2000)) }}
</figure> </figure>
{{ end }} {{ end }}
{{ with .Params.crew }}
{{ $photo := "" }}{{ with .image }}{{ $photo = resources.Get (strings.TrimPrefix "/" .) }}{{ end }}
<section class="wrap crew" aria-labelledby="crew-heading">
<h2 id="crew-heading" class="display">{{ .heading }}</h2>
<div class="crew__body">
<div class="crew__photo">
{{ if $photo }}
{{ partial "img.html" (dict "res" $photo "alt" (printf "Porträt von %s" .name) "sizes" "(min-width: 900px) 20rem, 60vw" "widths" (slice 400 800)) }}
{{ else }}
<span class="crew__initials" aria-hidden="true">{{ range split .name " " }}{{ substr . 0 1 }}{{ end }}</span>
{{ end }}
</div>
<div class="crew__info">
<h3 class="crew__name">{{ .name }}</h3>
<p class="crew__role">{{ .role }}</p>
{{ with .text }}<p class="crew__text">{{ . }}</p>{{ end }}
<a class="button button--ghost button--handle" href="{{ site.Params.photographer.instagram }}" target="_blank" rel="noopener">@{{ site.Params.photographer.handle }} auf Instagram</a>
</div>
</div>
</section>
{{ end }}
{{ end }} {{ end }}
+1
View File
@@ -23,6 +23,7 @@
<link rel="preload" href="/fonts/archivo-latin-400-normal.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/fonts/archivo-latin-400-normal.woff2" as="font" type="font/woff2" crossorigin>
{{ $css := resources.Get "css/main.css" | minify | fingerprint }} {{ $css := resources.Get "css/main.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}"> <link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}">
{{ partial "schema.html" . }}
</head> </head>
<body class="{{ if .IsHome }}is-home{{ end }}"> <body class="{{ if .IsHome }}is-home{{ end }}">
<a class="skip-link" href="#inhalt">Zum Inhalt springen</a> <a class="skip-link" href="#inhalt">Zum Inhalt springen</a>
+18
View File
@@ -0,0 +1,18 @@
{{- /*
Eigene Sitemap: Die Einzelseiten unter /shows/ sind noindex-Weiterleitungen
auf /shows/ und gehören nicht hinein. lastmod in der Zukunft (kommt von
kommenden Shows) wird weggelassen.
*/ -}}
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{{- range .Pages }}
{{- if and .Permalink (not (and (eq .Section "shows") (eq .Kind "page"))) }}
<url>
<loc>{{ .Permalink }}</loc>
{{- if and (not .Lastmod.IsZero) (le .Lastmod now) }}
<lastmod>{{ safeHTML (.Lastmod.Format "2006-01-02T15:04:05-07:00") }}</lastmod>
{{- end }}
</url>
{{- end }}
{{- end }}
</urlset>
+7 -4
View File
@@ -33,15 +33,18 @@
<h2 class="display">Live</h2> <h2 class="display">Live</h2>
<a class="text-link" href="/shows/">Alle Shows</a> <a class="text-link" href="/shows/">Alle Shows</a>
</header> </header>
{{ if $upcoming }} <h3 class="live__sub">Kommende Termine</h3>
{{ with $upcoming }}
<div class="flyer-wall"> <div class="flyer-wall">
{{ range $upcoming }}{{ partial "show-card.html" . }}{{ end }} {{ range . }}{{ partial "show-card.html" . }}{{ end }}
</div> </div>
{{ else }} {{ else }}
<p class="live__empty">Gerade sind keine Termine angekündigt. Ihr wollt uns auf eurer Bühne? Schreibt an <a href="mailto:{{ site.Params.email }}">{{ site.Params.email }}</a>.</p> <p class="live__empty">Gerade sind keine Termine angekündigt. Ihr wollt uns auf eurer Bühne? Schreibt an <a href="mailto:{{ site.Params.email }}">{{ site.Params.email }}</a>.</p>
<h3 class="live__sub">Zuletzt gespielt</h3> {{ end }}
{{ with $past }}
<h3 class="live__sub live__sub--past">Zuletzt gespielt</h3>
<div class="flyer-wall"> <div class="flyer-wall">
{{ range $past }}{{ partial "show-card.html" . }}{{ end }} {{ range . }}{{ partial "show-card.html" . }}{{ end }}
</div> </div>
{{ end }} {{ end }}
</section> </section>
+35 -17
View File
@@ -1,37 +1,55 @@
{{ define "main" }} {{ define "main" }}
{{ $releases := partial "releases.html" . }}
{{/* Hervorgehoben wird das neueste Album, ohne Album das neueste Release. */}}
{{ $featured := false }}
{{ with where $releases "kind" "Album" }}{{ $featured = index . 0 }}{{ else }}{{ with $releases }}{{ $featured = index . 0 }}{{ end }}{{ end }}
<header class="page-head wrap"> <header class="page-head wrap">
<h1 class="display display--xl">{{ .Title }}</h1> <h1 class="display display--xl">{{ .Title }}</h1>
{{ with .Content }}<div class="page-head__lead">{{ . }}</div>{{ end }} {{ with .Content }}<div class="page-head__lead">{{ . }}</div>{{ end }}
</header> </header>
<section class="wrap release"> {{ with $featured }}
{{ with .Params.album }} <section class="wrap album" aria-labelledby="album-title">
<div class="release__album"> <div class="album__sleeve">
<p class="release__kind">{{ .kind }}, {{ .year }}</p> <div class="album__vinyl" aria-hidden="true"></div>
<h2 class="release__title">{{ .title }}</h2> <div class="album__cover">
{{ with .text }}<p class="release__text">{{ . }}</p>{{ end }} {{ partial "img.html" (dict "res" .cover "alt" (printf "Cover von %s" .title) "sizes" "(min-width: 900px) 30rem, 80vw" "widths" (slice 480 800) "eager" true) }}
</div>
</div>
<div class="album__info">
<p class="album__kind">{{ .kind }}, erschienen am {{ .date | time.Format "2. January 2006" }}</p>
<h2 id="album-title" class="album__title">{{ .title }}</h2>
{{ with $.Params.albumText }}<p class="album__text">{{ . }}</p>{{ end }}
<a class="button button--bolt" href="{{ site.Params.spotify }}" target="_blank" rel="noopener">Auf Spotify hören</a> <a class="button button--bolt" href="{{ site.Params.spotify }}" target="_blank" rel="noopener">Auf Spotify hören</a>
</div> </div>
{{ end }}
<div class="release__player">
{{ partial "spotify.html" . }}
</div>
</section> </section>
{{ end }}
{{ with .Params.singles }} {{ $rest := slice }}
<section class="wrap singles" aria-labelledby="singles"> {{ range $releases }}{{ if or (not $featured) (ne .key $featured.key) }}{{ $rest = $rest | append . }}{{ end }}{{ end }}
<h2 id="singles" class="display">Singles</h2> {{ with $rest }}
<ol class="tracklist"> <section class="wrap discography" aria-labelledby="diskografie">
<h2 id="diskografie" class="display">Diskografie</h2>
<ol class="covers">
{{ range . }} {{ range . }}
<li> <li class="cover">
<span class="tracklist__title">{{ .title }}</span> <div class="cover__img">
{{ with .year }}<span class="tracklist__year">{{ . }}</span>{{ end }} {{ partial "img.html" (dict "res" .cover "alt" (printf "Cover von %s" .title) "sizes" "(min-width: 900px) 22rem, 45vw" "widths" (slice 400 800)) }}
</div>
<h3 class="cover__title">{{ .title }}</h3>
<p class="cover__meta">{{ .kind }}, <time datetime="{{ .date.Format "2006-01-02" }}">{{ .date | time.Format "2. January 2006" }}</time></p>
</li> </li>
{{ end }} {{ end }}
</ol> </ol>
</section> </section>
{{ end }} {{ end }}
<section class="wrap listen" aria-labelledby="reinhoeren">
<h2 id="reinhoeren" class="display">Reinhören</h2>
{{ partial "spotify.html" . }}
</section>
<section class="wrap elsewhere" aria-labelledby="elsewhere"> <section class="wrap elsewhere" aria-labelledby="elsewhere">
<h2 id="elsewhere" class="display">Mehr von uns</h2> <h2 id="elsewhere" class="display">Mehr von uns</h2>
<ul class="elsewhere__list"> <ul class="elsewhere__list">
+1
View File
@@ -12,6 +12,7 @@
</div> </div>
<div class="site-footer__legal"> <div class="site-footer__legal">
<p>© {{ now.Year }} Deepwater Survival</p> <p>© {{ now.Year }} Deepwater Survival</p>
{{ with site.Params.photographer }}<p>Alle Fotos von <a href="{{ .instagram }}" target="_blank" rel="noopener">@{{ .handle }}</a> ({{ .name }})</p>{{ end }}
<p><a href="/impressum/">Impressum</a> <a href="/datenschutz/">Datenschutz</a></p> <p><a href="/impressum/">Impressum</a> <a href="/datenschutz/">Datenschutz</a></p>
</div> </div>
</footer> </footer>
+4 -2
View File
@@ -1,13 +1,15 @@
{{/* {{/*
Responsives Bild aus static/img (über assets/img gemountet). Responsives Bild aus static/img (über assets/img gemountet).
Parameter: src (z. B. "/img/about/Olly_compressed.jpg"), alt, sizes, widths, class, eager Parameter: src (z. B. "/img/about/Olly_compressed.jpg") oder res (fertige Ressource),
alt, sizes, widths, class, eager
*/}} */}}
{{- $r := .res -}}
{{- $src := .src -}} {{- $src := .src -}}
{{- if $r }}{{ $src = $r.Name }}{{ else }}{{ $r = resources.Get (strings.TrimPrefix "/" $src) }}{{ end -}}
{{- $alt := .alt | default "" -}} {{- $alt := .alt | default "" -}}
{{- $sizes := .sizes | default "100vw" -}} {{- $sizes := .sizes | default "100vw" -}}
{{- $widths := .widths | default (slice 480 960 1600) -}} {{- $widths := .widths | default (slice 480 960 1600) -}}
{{- $loading := cond (.eager | default false) "eager" "lazy" -}} {{- $loading := cond (.eager | default false) "eager" "lazy" -}}
{{- $r := resources.Get (strings.TrimPrefix "/" $src) -}}
{{- if and $r (in (slice ".jpg" ".jpeg" ".png") (lower (path.Ext $src))) -}} {{- if and $r (in (slice ".jpg" ".jpeg" ".png") (lower (path.Ext $src))) -}}
{{- $set := slice -}} {{- $set := slice -}}
{{- $fallback := "" -}} {{- $fallback := "" -}}
+19
View File
@@ -0,0 +1,19 @@
{{/*
Liest alle Cover aus releases/ (gemountet nach assets/img/releases) und
gibt sie neueste zuerst zurück. Dateiname: 20250718_Album_OceanTales.jpg
*/}}
{{- $releases := slice -}}
{{- range resources.Match "img/releases/*" -}}
{{- $file := path.Base .Name -}}
{{- $base := strings.TrimSuffix (path.Ext $file) $file -}}
{{- $parts := split $base "_" -}}
{{- if ge (len $parts) 3 -}}
{{- $d := index $parts 0 -}}
{{- $title := delimit (after 2 $parts) " " -}}
{{- $title = replaceRE "([a-z])([A-Z])" "$1 $2" $title -}}
{{- $title = replace $title "'" "’" -}}
{{- $date := time.AsTime (printf "%s-%s-%s" (substr $d 0 4) (substr $d 4 2) (substr $d 6 2)) -}}
{{- $releases = $releases | append (dict "key" $d "date" $date "kind" (index $parts 1) "title" $title "cover" .) -}}
{{- end -}}
{{- end -}}
{{- return sort $releases "key" "desc" -}}
+64
View File
@@ -0,0 +1,64 @@
{{/*
JSON-LD für Suchmaschinen.
Startseite: die Band (MusicGroup) mit Besetzung, Album und Profilen.
/shows/: ein MusicEvent pro kommender Show mit Ort (TBA-Termine fehlen).
Optional im Show-Front-Matter: city (Ort, sonst wird location genommen)
und address (Straße und Hausnummer). Nur bestätigte Adressen eintragen.
*/}}
{{- $bandID := "/#band" | absURL -}}
{{- $band := dict "@type" "MusicGroup" "@id" $bandID "name" site.Title "url" site.Home.Permalink -}}
{{- if .IsHome -}}
{{- $band = merge $band (dict
"description" site.Params.description
"genre" "Punkrock"
"email" site.Params.email
"logo" ("/img/logo-crop.png" | absURL)
"location" (dict "@type" "Place" "name" "Trier" "address" (dict "@type" "PostalAddress" "addressLocality" "Trier" "addressCountry" "DE"))
"sameAs" (slice site.Params.spotify site.Params.instagram site.Params.youtube)
) -}}
{{- with resources.Get "img/AlbumReleaseParty_Stage_compressed.jpg" }}{{ with .Resize "1200x jpg q80" }}
{{- $band = merge $band (dict "image" .Permalink) -}}
{{- end }}{{ end -}}
{{- with site.GetPage "/about" }}{{ with .Params.members }}
{{- $members := slice -}}
{{- range . }}
{{- $members = $members | append (dict "@type" "OrganizationRole" "roleName" .role "member" (dict "@type" "Person" "name" .name)) -}}
{{- end }}
{{- $band = merge $band (dict "member" $members) -}}
{{- end }}{{ end -}}
{{- $albums := slice -}}
{{- range where (partial "releases.html" .) "kind" "Album" }}
{{- $album := dict "@type" "MusicAlbum" "name" .title "datePublished" (.date.Format "2006-01-02") "byArtist" (dict "@id" $bandID) -}}
{{- with .cover.Resize "800x webp q78" }}{{ $album = merge $album (dict "image" .Permalink) }}{{ end -}}
{{- $albums = $albums | append $album -}}
{{- end }}
{{- with $albums }}{{ $band = merge $band (dict "album" .) }}{{ end -}}
{{- $data := merge (dict "@context" "https://schema.org") $band }}
<script type="application/ld+json">{{ $data | jsonify | safeJS }}</script>
{{- end -}}
{{- if and (eq .Kind "section") (eq .Section "shows") -}}
{{- $events := slice -}}
{{- range (where .Pages "Date" "ge" now).ByDate }}
{{- if and (not .Params.tba) .Params.location }}
{{- $address := dict "@type" "PostalAddress" "addressLocality" (.Params.city | default .Params.location) "addressCountry" "DE" -}}
{{- with .Params.address }}{{ $address = merge $address (dict "streetAddress" .) }}{{ end -}}
{{- $event := dict
"@type" "MusicEvent"
"name" (printf "%s mit %s" .Title site.Title)
"startDate" (.Date.Format "2006-01-02")
"eventStatus" "https://schema.org/EventScheduled"
"eventAttendanceMode" "https://schema.org/OfflineEventAttendanceMode"
"location" (dict "@type" "Place" "name" .Params.location "address" $address)
"performer" $band
"url" $.Permalink
-}}
{{- with .Params.poster }}{{ $event = merge $event (dict "image" (. | absURL)) }}{{ end -}}
{{- $events = $events | append $event -}}
{{- end }}
{{- end }}
{{- with $events }}
<script type="application/ld+json">{{ dict "@context" "https://schema.org" "@graph" . | jsonify | safeJS }}</script>
{{- end }}
{{- end -}}
+16 -8
View File
@@ -1,18 +1,26 @@
{{- $r := "" -}} {{- $r := "" -}}
{{- with .Params.poster }}{{ $r = resources.Get (strings.TrimPrefix "/" .) }}{{ end -}} {{- $tba := .Params.tba -}}
<article class="flyer{{ if not $r }} flyer--blank{{ end }}"> {{- with .Params.poster }}{{ if not $tba }}{{ $r = resources.Get (strings.TrimPrefix "/" .) }}{{ end }}{{ end -}}
{{- if $r }} {{- $title := .Title | default "Neue Show" -}}
<a class="flyer__poster" href="{{ .Params.poster }}" target="_blank" rel="noopener" aria-label="Plakat {{ .Title }} in voller Größe öffnen"> <article class="flyer{{ if $tba }} flyer--tba{{ else if not $r }} flyer--blank{{ end }}">
{{ partial "img.html" (dict "src" .Params.poster "alt" (printf "Plakat: %s" .Title) "sizes" "(min-width: 900px) 280px, 45vw" "widths" (slice 320 640)) }} {{- if $tba }}
<div class="flyer__poster tba" aria-hidden="true">
<svg class="tba__bolt" viewBox="0 0 64 64" focusable="false"><path d="M30 6h18L36 28h12L28 58l6-24H20z"/></svg>
<span class="tba__big">TBA</span>
<span class="tba__band"><span>To be announced soon</span></span>
</div>
{{- else if $r }}
<a class="flyer__poster" href="{{ .Params.poster }}" target="_blank" rel="noopener" aria-label="Plakat {{ $title }} in voller Größe öffnen">
{{ partial "img.html" (dict "src" .Params.poster "alt" (printf "Plakat: %s" $title) "sizes" "(min-width: 900px) 280px, 45vw" "widths" (slice 320 640)) }}
</a> </a>
{{- else }} {{- else }}
<div class="flyer__poster flyer__poster--type" aria-hidden="true"> <div class="flyer__poster flyer__poster--type" aria-hidden="true">
<span>{{ .Title }}</span> <span>{{ $title }}</span>
</div> </div>
{{- end }} {{- end }}
<div class="flyer__caption"> <div class="flyer__caption">
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date | time.Format "2. January 2006" }}</time> <time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date | time.Format "2. January 2006" }}</time>
<h3>{{ .Title }}</h3> <h3>{{ $title }}</h3>
{{ with .Params.location }}<p>{{ . }}</p>{{ end }} {{ with .Params.location }}<p>{{ . }}</p>{{ else }}{{ if $tba }}<p>Ort folgt</p>{{ end }}{{ end }}
</div> </div>
</article> </article>
+4
View File
@@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: {{ "sitemap.xml" | absURL }}
Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 236 KiB