Files
Schmacko-napf/tools/build_pages.py
T

376 lines
20 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
OUT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
WP = "https://schmacko-napf.de/wp-content/uploads/"
LOGO = WP + "2024/12/Logo-Transparent-Rechnung.png"
KK = {n: f"{WP}2025/01/KK-Fotografie-{n}.jpg" for n in (35, 46, 51, 66)}
BARF = WP + "2023/06/Barf.png"
def U(pid, w=1600): return f"https://images.unsplash.com/photo-{pid}?auto=format&fit=crop&w={w}&q=80"
IMG_FOOD = "1714068691210-073dc52c6c1d"
IMG_SHOP = "1733451629760-d5fc1c818698"
IMG_CAR = "1771777400696-3af9b6470ff8"
PHONE, PHONE_HREF = "+49 176 569 329 42", "tel:+4917656932942"
MAIL = "info@schmacko-napf.de"
WA = "https://wa.me/4917656932942"
def ic(d, sw="1.8"):
return f'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="{sw}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">{d}</svg>'
I = {
"arrow": ic('<path d="M5 12h14M13 6l6 6-6 6"/>', "2"),
"down": ic('<path d="M12 5v14M6 13l6 6 6-6"/>', "2"),
"menu": ic('<path d="M4 7h16M4 12h16M4 17h16"/>', "2"),
"phone": ic('<path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2"/>'),
"mail": ic('<rect x="3" y="5" width="18" height="14" rx="2.5"/><path d="m4 7 8 6 8-6"/>'),
"chat": ic('<path d="M20 11.5a8 8 0 0 1-11.8 7L4 20l1.5-4A8 8 0 1 1 20 11.5z"/>'),
"bowl": ic('<path d="M3 12h18a9 9 0 0 1-18 0z"/><path d="M8 8c0-2 2-2 2-4M13 8c0-2 2-2 2-4"/>'),
"bone": ic('<path d="M8 8 16 16M6.5 4.5a2 2 0 0 0-2 2 2 2 0 1 0 3 2.5l7.5 7.5a2 2 0 1 0 2.5 3 2 2 0 0 0 2-2 2 2 0 1 0-2.5-3L9.5 7a2 2 0 0 0-3-2.5z"/>'),
"leash": ic('<circle cx="17" cy="7" r="3"/><path d="M15 9.5 6 19M4 17l3 3"/>'),
"car": ic('<path d="M5 16V11l2-5h10l2 5v5"/><path d="M3 16h18v3H3z"/><circle cx="7.5" cy="13" r="1"/><circle cx="16.5" cy="13" r="1"/>'),
"shield": ic('<path d="M12 3 5 6v6c0 4.5 3 7.5 7 9 4-1.5 7-4.5 7-9V6z"/><path d="m9 12 2 2 4-4"/>'),
"wind": ic('<path d="M3 9h11a3 3 0 1 0-3-3M3 15h15a3 3 0 1 1-3 3M3 12h8"/>'),
}
ARROW_BADGE = f'<span class="panel-arrow">{I["arrow"]}</span>'
NAV = [("hundeschule.html", "Hundetraining"), ("ernaehrung.html", "Ernährung"), ("shop.html", "Shop"),
("transportboxen.html", "Transportboxen"), ("index.html#kontakt", "Kontakt")]
def head(title, desc):
return f'''<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{title}</title>
<meta name="description" content="{desc}">
<meta name="theme-color" content="#fcfaf4">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='12' fill='%23194242'/%3E%3C/svg%3E">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Questrial&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/site.css">
</head>
'''
def header(current=None):
cur = ' aria-current="page"'
links = "\n".join(f' <a href="{h}"{cur if h == current else ""}>{t}</a>' for h, t in NAV)
return f''' <header class="site-header">
<div class="header-inner">
<a class="brand" href="index.html" aria-label="Schmacko Napf – Startseite"><img src="{LOGO}" alt="Schmacko Napf &amp; Hundetraining by Katha"></a>
<nav class="nav" aria-label="Hauptmenü">
{links}
</nav>
<button class="burger" type="button" aria-label="Menü öffnen" aria-expanded="false">{I["menu"]}</button>
</div>
</header>
'''
def contact(photo=KK[46], alt="Schwarze Schäferhündin steht aufmerksam im Wald"):
go = f'<span>{I["arrow"]}</span>'
return f''' <div class="row row--wide" id="kontakt">
<div class="panel panel--ink reveal">
<span class="kicker">Kontakt</span>
<h2 class="display">Lass uns<br>sprechen.</h2>
<div class="contact-links">
<a href="{WA}" target="_blank" rel="noopener">{I["chat"]}<span>WhatsApp</span>{go}</a>
<a href="{PHONE_HREF}">{I["phone"]}<span>{PHONE}</span>{go}</a>
<a href="mailto:{MAIL}">{I["mail"]}<span>{MAIL}</span>{go}</a>
</div>
</div>
<div class="panel panel--photo plain reveal d1"><img src="{photo}" alt="{alt}" loading="lazy"></div>
</div>
'''
def footer():
return f''' <footer class="site-footer">
<div class="footer-brand">
<a class="footer-logo" href="index.html"><img src="{LOGO}" alt="Schmacko Napf &amp; Hundetraining by Katha"></a>
<span>Ernährung, Gesundheit und Training –<br>mit Herz und Verstand.</span>
</div>
<nav class="footer-links" aria-label="Footer">
<a href="hundeschule.html">Hundetraining</a>
<a href="ernaehrung.html">Ernährung</a>
<a href="shop.html">Shop</a>
<a href="transportboxen.html">Transportboxen</a>
<a href="impressum.html">Impressum</a>
<a href="#">Datenschutz</a>
</nav>
<div class="footer-meta"><span>© 2026 Schmacko Napf &amp; Hundetraining by Katha</span><span>Fotos: Steffi Biller, KK-Fotografie</span></div>
</footer>
</main>
<script src="assets/site.js"></script>
</body>
</html>
'''
def page_hero(img, kicker, title, text, alt):
return f''' <section class="panel panel--photo page-hero">
<img src="{img}" alt="{alt}">
<span class="kicker">{kicker}</span>
<h1>{title}</h1>
<p class="big">{text}</p>
</section>
'''
def page(name, title, desc, current, body):
write(name, head(title, desc) + "<body>\n" + header(current) + ' <main class="mosaic">\n' + body + footer())
def write(name, html):
open(os.path.join(OUT, name), "w").write(html)
# ================================================================ Startseite
tiles = [
("hundeschule.html", "Hundeschule", "", KK[66], "Katha mit ihrem Hund auf einer Wiese im Abendlicht", None),
("ernaehrung.html", "Ernährungsberatung", "", U(IMG_FOOD, 1400), "Hund schnuppert an einem Napf mit Trockenfutter", IMG_FOOD),
("shop.html", "Shop", "", U(IMG_SHOP, 1400), "Hund in einem Laden mit Hundezubehör", IMG_SHOP),
("transportboxen.html", "Transportboxen", "Maßanfertigung fürs Auto", U(IMG_CAR, 1400), "Hund sitzt im offenen Kofferraum hinter einem Trenngitter", IMG_CAR),
]
tile_html = ""
for href, name, sub, src, alt, pid in tiles:
small = f"<small>{sub}</small>" if sub else ""
srcset = f' srcset="{U(pid,800)} 800w, {U(pid,1400)} 1400w, {U(pid,2000)} 2000w" sizes="(max-width: 767px) 100vw, 50vw"' if pid else ""
tile_html += f''' <a class="tile" href="{href}">
<img src="{src}"{srcset} alt="{alt}">
<span class="tile-foot">
<span class="tile-label">{name}{small}</span>
<span class="tile-arrow">{I["arrow"]}</span>
</span>
</a>
'''
index = head("Schmacko Napf & Hundetraining by Katha", "Hundetraining, Ernährungs- und Gesundheitsberatung, Shop und maßgefertigte Transportboxen – Schmacko Napf by Katha.") + '<body class="is-home">\n' + header() + f''' <section class="hero">
<nav class="tiles" aria-label="Bereiche">
<svg class="seal-joint" aria-hidden="true"><path/></svg>
<h1 class="seal"><img src="{LOGO}" alt="Schmacko Napf &amp; Hundetraining by Katha"></h1>
{tile_html} <a class="scroll-hint" href="#ueber-mich" aria-label="Weiter nach unten">{I["down"]}</a>
</nav>
</section>
<main class="mosaic">
<div class="row row--wide-r" id="ueber-mich">
<div class="panel panel--cream reveal">
<span class="kicker">Über mich</span>
<h2 class="display">Hallo,<br>ich bin Katha.</h2>
<p class="big">Hundetrainerin und Ernährungsberaterin – mit Herz und Verstand. Für beide Seiten der Leine.</p>
<div class="facts">
<span class="fact">§ 11 TierSchG zertifiziert</span>
<span class="fact">Ernährungs- &amp; Gesundheitsberaterin</span>
</div>
</div>
<div class="panel panel--photo plain reveal d1"><img src="{KK[35]}" alt="Katha sitzt mit ihrer Schäferhündin Elina im Grünen" loading="lazy"></div>
</div>
<a class="panel panel--photo tall reveal" href="hundeschule.html">
<img src="{KK[51]}" alt="Schwarzer Schäferhund rennt freudig über einen Feldweg" loading="lazy">
{ARROW_BADGE}
<span class="kicker">Hundetraining</span>
<h2 class="display">Entspannt durch<br>den Alltag.</h2>
<p class="big">Einzeltraining, Hausbesuch und Außentraining in der Gruppe.</p>
<div class="facts">
<span class="fact">Einzeltraining 60 € / Std.</span>
<span class="fact">Gruppe 18 €</span>
<span class="fact">10er-Karte 165 €</span>
</div>
</a>
<div class="row">
<div class="panel panel--sage plate-panel reveal"><img src="{BARF}" alt="Teller mit frischem Fleisch, Gemüse und Obst für die Rohfütterung" loading="lazy"></div>
<a class="panel panel--cream reveal d1" href="ernaehrung.html">
<span class="panel-arrow" style="background:var(--ink);border-color:var(--ink)">{I["arrow"]}</span>
<span class="kicker">Ernährungsberatung</span>
<h2 class="display">Gesund<br>gefüttert.</h2>
<p class="big">Individuelle Futterpläne – für jedes Alter, auch bei Magen-Darm- oder Pankreas-Problemen.</p>
<div class="facts"><span class="fact">BARF</span><span class="fact">Koch-BARF</span><span class="fact">Nass- &amp; Trockenfutter</span></div>
</a>
</div>
<div class="panel panel--plain panel--mid panel--center reveal">
<p class="statement">„Futter ist mehr als nur Nahrung – es ist Fürsorge in Napfform.“</p>
<span class="statement-by">— Katha</span>
</div>
<div class="panel panel--ink panel--auto reveal">
<span class="kicker">Meine Philosophie · die 5 Säulen</span>
<ul class="words">
<li><small>01</small>Respekt<span>Den Hund als eigenständiges Wesen ernst nehmen.</span></li>
<li><small>02</small>Ehrlichkeit<span>Klare Signale schaffen Vertrauen.</span></li>
<li><small>03</small>Geduld<span>Jeder Hund lernt in seinem Tempo.</span></li>
<li><small>04</small>Konsequenz<span>Klare Regeln – fair und ohne Druck.</span></li>
<li><small>05</small>Verständnis<span>Bedürfnisse und Gefühle verstehen.</span></li>
</ul>
</div>
<div class="row">
<a class="panel panel--photo reveal" href="shop.html">
<img src="{U(IMG_SHOP)}" alt="Hund in einem Laden mit Hundezubehör" loading="lazy">
{ARROW_BADGE}
<span class="kicker">Shop</span>
<h2 class="title">Futter, Snacks<br>&amp; Zubehör.</h2>
</a>
<a class="panel panel--photo reveal d1" href="transportboxen.html">
<img src="{U(IMG_CAR)}" alt="Hund sitzt im Kofferraum hinter einem Trenngitter" loading="lazy">
{ARROW_BADGE}
<span class="kicker">Maßanfertigung</span>
<h2 class="title">Transportboxen<br>fürs Auto.</h2>
</a>
</div>
{contact()}''' + footer().replace(" </main>\n", " </main>\n", 1)
write("index.html", index)
# ================================================================ Hundetraining
page("hundeschule.html", "Hundetraining – Schmacko Napf",
"Einzeltraining, Hausbesuche und Gruppentraining im Außenbereich mit Katha, zertifizierte Hundetrainerin nach § 11 TierSchG.",
"hundeschule.html",
page_hero(KK[66], "Hundetraining", "Für beide Seiten<br>der Leine.",
"Vertrauen, klare Kommunikation und Training, das im Alltag funktioniert.",
"Katha mit ihrem Hund auf einer Wiese im Abendlicht") + f'''
<div class="row row--wide-r">
<div class="panel panel--cream reveal">
<span class="kicker">Einzeltraining &amp; Hausbesuch</span>
<h2 class="title">Individuell.<br>Bei dir zu Hause.</h2>
<p class="big">Für Grundgehorsam, Unsicherheit, Leinenführigkeit oder einen neuen Hund im Haus.</p>
<div class="price-big"><strong>60 €</strong><span>pro Stunde · nach dem Erstgespräch (120 €, ca. 2 Std.)</span></div>
</div>
<div class="panel panel--photo plain reveal d1"><img src="{KK[46]}" alt="Schwarze Schäferhündin steht aufmerksam im Wald" loading="lazy"></div>
</div>
<div class="row row--wide">
<div class="panel panel--photo plain reveal"><img src="{KK[51]}" alt="Schwarzer Schäferhund rennt über einen Feldweg" loading="lazy"></div>
<div class="panel panel--ink reveal d1">
<span class="kicker">Gruppe &amp; Außentraining</span>
<h2 class="title">Training da, wo<br>das Leben ist.</h2>
<p class="big">In der Stadt, im Grünen, in Geschäften – mit max. 6 Mensch-Hund-Teams.</p>
<div class="price-big"><strong>18 €</strong><span>pro Mensch-Hund-Team</span></div>
</div>
</div>
<div class="panel panel--ink panel--auto reveal">
<span class="kicker">Die 5 Säulen</span>
<ul class="words">
<li><small>01</small>Respekt<span>Hunde wollen ernst genommen werden.</span></li>
<li><small>02</small>Ehrlichkeit<span>Hunde lesen unsere Körpersprache sofort.</span></li>
<li><small>03</small>Geduld<span>Lernen braucht Zeit und Wiederholung.</span></li>
<li><small>04</small>Konsequenz<span>Klare Regeln, ganz ohne Gewalt.</span></li>
<li><small>05</small>Verständnis<span>Realistische Erwartungen an jeden Hund.</span></li>
</ul>
</div>
<div class="panel panel--cream panel--auto reveal">
<span class="kicker">Preise</span>
<h2 class="title">Fair und klar.</h2>
<div class="price-rows">
<div><span>Erstgespräch Einzeltraining<small>ca. 2 Stunden · zzgl. 0,30 € / km</small></span><strong>120 €</strong></div>
<div><span>Einzeltraining<small>pro Stunde · zzgl. 0,30 € / km</small></span><strong>60 €</strong></div>
<div><span>Gruppentraining<small>pro Mensch-Hund-Team</small></span><strong>18 €</strong></div>
<div><span>10er-Karte<small>Gruppe &amp; Einzel frei kombinierbar</small></span><strong>165 €</strong></div>
</div>
</div>
{contact(KK[35], "Katha sitzt mit ihrer Schäferhündin im Grünen")}''')
# ================================================================ Ernährung
page("ernaehrung.html", "Ernährungsberatung – Schmacko Napf",
"Individuelle Futterpläne und Gesundheitsberatung für Hunde jeden Alters – BARF, Koch-BARF, Nass- und Trockenfutter.",
"ernaehrung.html",
page_hero(U(IMG_FOOD, 2000), "Ernährungs- &amp; Gesundheitsberatung", "Fürsorge<br>in Napfform.",
"Individuelle Futterpläne – gesund, sensibel oder mit Diagnose.",
"Hund schnuppert an einem Napf mit Trockenfutter") + f'''
<div class="row">
<div class="panel panel--cream reveal">
<span class="kicker">Kennst du das?</span>
<h2 class="title">Jeder sagt<br>etwas anderes.</h2>
<p class="big">Ich bringe Klarheit in die Futter-Frage – und erstelle einen Plan, der zu deinem Hund passt.</p>
<div class="facts"><span class="fact">BARF</span><span class="fact">Teil-BARF</span><span class="fact">Koch-BARF</span><span class="fact">Nassfutter</span><span class="fact">Trockenfutter</span></div>
</div>
<div class="panel panel--sage plate-panel reveal d1"><img src="{BARF}" alt="Teller mit frischem Fleisch, Gemüse und Obst" loading="lazy"></div>
</div>
<div class="panel panel--ink panel--auto reveal">
<span class="kicker">Ablauf</span>
<h2 class="title">So starten wir.</h2>
<ol class="steps">
<li><b>01</b><strong>Erstgespräch</strong><span>Vor Ort, am Telefon oder online.</span></li>
<li><b>02</b><strong>Futterplan</strong><span>Genau auf deinen Hund abgestimmt.</span></li>
<li><b>03</b><strong>Fragen klären</strong><span>Nach 3 Tagen gehen wir alles durch.</span></li>
<li><b>04</b><strong>Nachbesprechung</strong><span>Nach 4 Wochen schauen wir gemeinsam drauf.</span></li>
</ol>
</div>
<div class="row row--3">
<div class="panel panel--cream panel--mid reveal">
<span class="kicker">Rationsprüfung</span>
<h2 class="title">Passt das<br>Futter?</h2>
<div class="price-big"><strong>kostenlos</strong></div>
</div>
<div class="panel panel--sage panel--mid reveal d1">
<span class="kicker">Erstgespräch</span>
<h2 class="title">Kennen&shy;lernen</h2>
<div class="price-big"><strong>ab 45 €</strong><span>ca. 60 Minuten</span></div>
</div>
<div class="panel panel--ink panel--mid reveal d2">
<span class="kicker">Futterplan</span>
<h2 class="title">Dein<br>Plan</h2>
<div class="price-big"><strong>ab 75 €</strong><span>inkl. Folgegespräch nach 4 Wochen</span></div>
</div>
</div>
{contact()}''')
# ================================================================ Shop
page("shop.html", "Shop – Schmacko Napf", "Ausgewähltes Futter, Snacks und Zubehör für deinen Hund.", "shop.html",
page_hero(U(IMG_SHOP, 2000), "Shop", "Ausgewählt<br>mit Herz.",
"Futter, Snacks und Zubehör, hinter denen ich stehe.",
"Hund in einem Laden mit Hundezubehör") + f'''
<div class="row row--3">
<div class="panel panel--cream panel--mid reveal"><div class="panel-icon">{I["bowl"]}</div><h2 class="title">Futter</h2><p class="big">Passend zu deinem Futterplan.</p></div>
<div class="panel panel--sage panel--mid reveal d1"><div class="panel-icon">{I["bone"]}</div><h2 class="title">Snacks</h2><p class="big">Natürlich – fürs Training und zum Belohnen.</p></div>
<div class="panel panel--ink panel--mid reveal d2"><div class="panel-icon">{I["leash"]}</div><h2 class="title">Zubehör</h2><p class="big">Robust und durchdacht für den Alltag.</p></div>
</div>
<div class="panel panel--cream panel--mid panel--center reveal">
<p class="statement">Der Online-Shop ist bald da.<br>Bis dahin: schreib mir einfach.</p>
</div>
{contact()}''')
# ================================================================ Transportboxen
page("transportboxen.html", "Transportboxen nach Maß – Schmacko Napf",
"Maßgefertigte Hunde-Transportboxen fürs Auto – passgenau für Fahrzeug und Hund.", "transportboxen.html",
page_hero(U(IMG_CAR, 2000), "Maßanfertigung", "Transportboxen<br>fürs Auto.",
"Passgenau für dein Fahrzeug und deinen Hund.",
"Hund sitzt im offenen Kofferraum hinter einem Trenngitter") + f'''
<div class="row row--3">
<div class="panel panel--cream panel--mid reveal"><div class="panel-icon">{I["car"]}</div><h2 class="title">Passgenau</h2><p class="big">Exakt für deinen Kofferraum gebaut.</p></div>
<div class="panel panel--sage panel--mid reveal d1"><div class="panel-icon">{I["shield"]}</div><h2 class="title">Sicher</h2><p class="big">Stabil – für jede Fahrt.</p></div>
<div class="panel panel--ink panel--mid reveal d2"><div class="panel-icon">{I["wind"]}</div><h2 class="title">Bequem</h2><p class="big">Luftig und mit genug Platz.</p></div>
</div>
<div class="panel panel--ink panel--auto reveal">
<span class="kicker">Ablauf</span>
<h2 class="title">In 4 Schritten zur eigenen Box.</h2>
<ol class="steps">
<li><b>01</b><strong>Beratung</strong><span>Auto, Hund und Wünsche.</span></li>
<li><b>02</b><strong>Ausmessen</strong><span>Kofferraum und Hund genau vermessen.</span></li>
<li><b>03</b><strong>Fertigung</strong><span>Deine Box entsteht nach Maß.</span></li>
<li><b>04</b><strong>Übergabe</strong><span>Einbau – und los geht’s.</span></li>
</ol>
</div>
{contact()}''')
# ================================================================ Impressum
page("impressum.html", "Impressum – Schmacko Napf", "Impressum von Schmacko Napf & Hundetraining by Katha.", None, f''' <div class="panel panel--cream panel--auto">
<span class="kicker">Rechtliches</span>
<h1 class="display">Impressum</h1>
<div class="legal" style="margin-top:48px">
<p><b>Angaben gemäß § 5 TMG</b>Katharina Schulz<br>Seewiese 19<br>84109 Wörth a.d. Isar</p>
<p><b>Kontakt</b>Telefon: {PHONE}<br>E-Mail: {MAIL}</p>
<p><b>Verantwortlich gemäß § 18 Abs. 2 MStV</b>Katharina Schulz, Anschrift wie oben</p>
<p><b>Fotos</b>Steffi Biller, KK-Fotografie · weitere Bilder: Unsplash</p>
</div>
</div>
''')
print("ok")