]> git.laktatnebel.de Git - www.triathlon-coaching.com.git/commitdiff
DB-Setup mit Artikeln
authorOle B. Rosentreter <ole@laktatnebel.de>
Wed, 18 Mar 2026 17:02:46 +0000 (18:02 +0100)
committerOle B. Rosentreter <ole@laktatnebel.de>
Wed, 18 Mar 2026 17:02:46 +0000 (18:02 +0100)
28 files changed:
db/articles/001_index.sql [new file with mode: 0644]
db/articles/002_coaching.sql [new file with mode: 0644]
db/articles/003_blog.sql [new file with mode: 0644]
db/articles/004_camps.sql [new file with mode: 0644]
db/articles/005_tools.sql [new file with mode: 0644]
db/articles/006_kontakt.sql [new file with mode: 0644]
db/articles/007_impressum.sql [new file with mode: 0644]
db/articles/008_datenschutz.sql [new file with mode: 0644]
db/articles/009_agb.sql [new file with mode: 0644]
db/articles/010_personal-coaching.sql [new file with mode: 0644]
db/articles/011_standard-plaene.sql [new file with mode: 0644]
db/articles/012_langdistanz.sql [new file with mode: 0644]
db/articles/013_mitteldistanz.sql [new file with mode: 0644]
db/articles/014_kurzdistanz.sql [new file with mode: 0644]
db/articles/015_blog_warum-einen-coach.sql [new file with mode: 0644]
db/articles/016_blog_gesundheit.sql [new file with mode: 0644]
db/articles/017_blog_mittwochs-faengt-die-woche-an.sql [new file with mode: 0644]
db/articles/018_blog_mein-coaching-ansatz.sql [new file with mode: 0644]
db/articles/019_blog_grenzen-wofur-ich-nicht-da-bin.sql [new file with mode: 0644]
db/articles/020_blog_ziele-setzen-aber-richtig.sql [new file with mode: 0644]
db/articles/021_blog_wenn-du-krank-bist.sql [new file with mode: 0644]
db/articles/022_blog_was-nicht-auf-strava-ist-ist-nicht-passiert.sql [new file with mode: 0644]
db/articles/023_blog_laufschuhe-kann-man-zu-viele-haben.sql [new file with mode: 0644]
db/articles/024_blog_bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn.sql [new file with mode: 0644]
db/articles/025_blog_warm-up-vor-einem-laufwettkampf.sql [new file with mode: 0644]
db/articles/026_blog_saisonplanung-wie-geht-man-vor.sql [new file with mode: 0644]
db/dump-laktatnebel-202603181341_schema.sql [new file with mode: 0644]
db/dump-laktatnebel-202603181342_data.sql [new file with mode: 0644]

diff --git a/db/articles/001_index.sql b/db/articles/001_index.sql
new file mode 100644 (file)
index 0000000..52f9f1f
--- /dev/null
@@ -0,0 +1,84 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'index', NULL, 'home', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, NULL, (SELECT id FROM :"schema".pages WHERE slug='index'), NULL, 'Über mich', 0, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='index'), 1, NULL, 'Erfahrung, die zählt.', 'Coaching, das aus echter Wettkampferfahrung entsteht.', 'Über mich', 'Seit 1997 im Triathlon. Seit 2018 lizensierter DTU-C-Trainer.', '## Wer bin ich?
+
+Seit 1987 bin ich Läufer und seit 1997 Triathlet – zum großen Teil leistungssportlich. Zwischen 800m und Ironman habe ich keine Strecke ausgelassen. Anders ausgedrückt: Ich spreche bei meinem Training viel aus Erfahrung und kenne sowohl die Einsamkeit der langen Radausfahrt als auch die Hektik auf der Tartanbahn.
+
+![Foto](https://www.triathlon-coaching.com/wp-content/uploads/2024/09/IMG-20200628-WA0013-e1611777541756-300x300.jpg)
+
+Kaum kürzer ist mein Interesse an der Trainingslehre und Sportwissenschaft. So begleitete mich über die Jahre als Athleten bald die Rolle des Trainers, Übungsleiters, Radguides, usw. Das hilft mir, meine langjährigen Erfahrungen und persönlichen Lektionen in meine Trainertätigkeit einfließen zu lassen.
+
+Seit 2018 bin ich auch lizensierter DTU-C-Trainer.
+
+### Die ganze Wahrheit:
+
+Wie fing es an?  
+Schwimmen war ich beim DLRG und 1986 faszinierte mich die Fußball-WM in Mexiko so sehr, dass ich mit den Anderen den ganzen Sommer über den Bolzplatz rannte. Da wurde ich wohl auch recht fit. Zumindest so fit, dass in der Schule die 1000m schon mal in 3:30 gingen. Damit war ich vorne dabei. Ganz ohne Leichtathletikverein, ohne irgendein Training.
+
+1987, als 14-Jähriger, schnürte ich das erste Mal meine Schuhe, um mit meinem Vater eine Runde zu drehen. Nicht viel später folgte der erste Volkslauf über 10km.
+
+### Marathon mit 16 :-/  
+Der Einfluß des örtlichen Laufvereins und Bücher wie der Manfred Steffnys Klassiker „Marathontraining" ließen mich gleich die langen Laufstrecken anstreben; mit 16 lief ich dann 1989 in Berlin meinen ersten Marathon in 3:10:51.  
+
+Und ungefähr zu der Zeit erschien in der Sonntagsbeilage der FAZ eine Reportage über Dirk Aschmoneit, einer der ersten richtig guten deutschen Triathleten zusammen mit Wolfgang Dittrich und Jürgen Zäck. Und es hat mich fasziniert: Hawaii: Da muß ich hin!  
+
+*Fun fact:* Die Ausgabe habe ich viele Jahre später in einem Antiquariat wiedergefunden und gekauft.
+
+Weitere Beschäftigung mit sportwissenschaftlichen Themen, Trainingslehre und dem Thema sportliche Entwicklung ließen die Erkenntnis reifen, dass ich „untenrum" schneller werden muss, um auf der langen Strecke auch schnell zu sein.
+
+### Der Geruch von Tartan  
+Also wechselte ich zu einer guten, jungen Trainingsgruppe, um dann auf der Bahn zu trainieren und Wettkämpfe zu bestreiten. Und zu Lernen: Lauf-ABC, Athletiktraining, Taktiken, exaktes Pacing - auf der Bahn was ganz anderes als im Triathlon - aber als Erfahrung unendlich wertvoll. Bis heute.  
+
+Und bis heute mag ich den Geruch von Tartan. Riecht nach ehrlichem Sport. Keine Diskussion über die Strecke: 400m sind 400m.
+
+Aus der Zeit kamen auch noch einige Bestzeiten, die auch über 30 Jahre später noch stehen: 800m: 1:58,3 – 3000m: 8:42,4 – 5000m: 15:25,68.  
+
+Ach so: 1991 machte ich meinen ersten (Volks-)Triathlon in Neuss.
+
+Eine ganz andere wertvolle Erfahrung war etwas anderes: Ich habe einem Freund aus meiner damaligen Trainingsgruppe Trainingspläne geschrieben. Und die funktionierten auch noch! Gefuchst hat es mich schon, dass Uwe dann auf 10000m schneller war als ich. Weitere wichtige Erkenntnis: Er hat halt konsequenter trainiert als ich. ;-)
+
+### Back to the Roads
+Mit dem Juniorenalter war dann die Straßenlaufdistanz für Meisterschaften im DLV wieder länger. Halbmarathon. Das ist zwar „nur" 6km länger als die 15km, aber die Tücke liegt im Wort: Marathon. Die Strecken wurden wieder länger, neue Bestzeiten kamen dazu: 10000m: 31:49,98 – Halbmarathon 1:14:10 – Marathon: 2:46:23  
+
+Ganz ehrlich ist das nicht wirklich flott und weit weg von richtig gut. Mit 1,88m ist man zu schwer für die Langstrecke und auf der Mittelstrecke sind 54,0 auf 400m ein zu stumpfes Schwert. So kam es wie es kommen musste: Nach Achillessehnenreizung Nummer X sagte ich mir: Bei der nächsten Verletzung wechsle ich zum Triathlon. Spoiler: Hat nicht lang gedauert.... ;-)
+
+### Schwimmen, Radfahren, Laufen - ja, aber wie?
+Wir schreiben das Jahr 1997. Qua selbstgefasstem Beschluß wurde ich Triathlet. Schön, Schwimmen im Sinne von mit viel Einsatz halbwegs zügig voran kommen konnte ich. Ein olles Rennrad - sogar mit Aufsatz (lang lebe der Syntace C2 Clip) - hatte ich. Gut, Laufen - davon hatte ich Ahnung.
+
+Laufliteratur gab es damals schon zur Genüge, das Internet war noch eher den Tech-Freaks vorbehalten, aber Triathlontraining wie wir es heute kennen war eigentlich noch nicht wirklich erfunden und Bücher entsprechend selten. So musste ich mir die ganz grundlegenden Dinge der Sportwissenschaften auf den Ausdauerdreikampf anwenden. Und ausprobieren. Und lernen. Vor allem beim Radfahren war ich anfangs völlig ahnungslos.
+
+### Roth, Roth, Roth und NRW-Liga
+Seit dem Ironman Europe in Roth 1998 darf ich mich Ironman nennen. In dieser Zeit startete ich auch in der NRW-Liga, zu der Zeit noch ohne Windschattenfreigabe. Mein damaliger Verein wuchs und hatte bald auch Damen-, Senioren und Masters-Teams in der Liga. Und somit eine schöne Trainingsgruppe, die ich in die Geheimnisse des Laufens einweihen durfte ;-)  
+
+Zu dieser Zeit begann auch sowas wie Trainingssteuerung: Dank eines Laktatmessgerätes habe ich dann recht regelmäßig Laktattests durchgeführt und anhand der diagnostizierten Schwellen die Trainingsbereiche festgelegt und Trainingspläne geschrieben. Immerhin schon mit dem PC in Excel-Tabellen.
+
+### Real life
+Irgendwann wurde es dann doch notwendig, beruflich Fuß zu fassen - ich bin hauptberuflich in der IT unterwegs - und die sonst üblichen Dinge zu tun: Haus bauen, Sohn (2x) zeugen, Baum pflanzen und dafür den Sport auf „hin und wieder Bewegung an frischer Luft" zu reduzieren.
+
+Aber wie es so ist: Leidenschaften sterben nie und so bin ich dem Sport letztendlich treu geblieben. Und je mehr Erfahrung und Wissen man sammelt, je mehr kann man weitergeben.
+', '## 1987 – Die ersten Schritte
+
+Mit 14 Jahren die ersten Laufschuhe geschnürt – zusammen mit meinem Vater. Nicht viel später folgte der erste Volkslauf über 10 km.
+
+## 1989 – Marathon mit 16
+
+Berlin, erster Marathon: 3:10:51. Der Beginn einer langen Liebe zur langen Strecke – und zu Hawaii als großem Ziel.
+
+## 1991 – Der Geruch von Tartan
+
+Bahntraining, Wettkämpfe, Lauf-ABC. Bestzeiten die bis heute stehen: 800m 1:58,3 · 3000m 8:42,4 · 5000m 15:25. Und: erster Volkstriathlon in Neuss.
+
+## 1997 – Triathlet werden
+
+Qua selbstgefasstem Beschluß wurde ich Triathlet. Schwimmen: irgendwie. Rad: ein olles Rennrad. Laufen: davon hatte ich Ahnung.
+
+## 1998 – Ironman Roth
+
+Ironman Europe in Roth – seitdem darf ich mich Ironman nennen. NRW-Liga, Laktatmessungen, Trainingspläne in Excel.
+
+## 2018 – DTU-C-Trainer
+
+Lizensierter Trainer des Deutschen Triathlon Union – die offizielle Bestätigung eines langen Wegs aus Erfahrung, Leidenschaft und Sportwissenschaft.', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/002_coaching.sql b/db/articles/002_coaching.sql
new file mode 100644 (file)
index 0000000..2713de5
--- /dev/null
@@ -0,0 +1,6 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'coaching', NULL, 'category-grid', 1, true, 'coaching', NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, NULL, (SELECT id FROM :"schema".pages WHERE slug='coaching'), NULL, 'Coaching', 1, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='coaching'), 1, NULL, 'Coaching', 'Das richtige Angebot für dein Ziel.', 'Angebot', NULL, '', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/003_blog.sql b/db/articles/003_blog.sql
new file mode 100644 (file)
index 0000000..76f1733
--- /dev/null
@@ -0,0 +1,6 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog', NULL, 'blog-grid', 2, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, NULL, (SELECT id FROM :"schema".pages WHERE slug='blog'), NULL, 'Blog', 2, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog'), 1, NULL, 'Blog', 'Über Training, Taktik, Ernährung, Equipment und alles, was Läufer & Triathleten bewegt.', 'Wissen & Erfahrung', NULL, '', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/004_camps.sql b/db/articles/004_camps.sql
new file mode 100644 (file)
index 0000000..1392c85
--- /dev/null
@@ -0,0 +1,6 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'camps', NULL, 'content-page', 3, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, NULL, (SELECT id FROM :"schema".pages WHERE slug='camps'), NULL, 'Camps', 3, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='camps'), 1, NULL, 'Camps', NULL, 'Gemeinsam trainieren', NULL, '', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/005_tools.sql b/db/articles/005_tools.sql
new file mode 100644 (file)
index 0000000..4d48666
--- /dev/null
@@ -0,0 +1,8 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'tools', NULL, 'tool-grid', 4, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, NULL, (SELECT id FROM :"schema".pages WHERE slug='tools'), NULL, 'Tools & more', 4, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='tools'), 1, NULL, 'Tools & more', 'Spezialisierte Plattformen rund um Schwimmtraining und Wettkampfvorbereitung.', 'Interaktiv & spezialisiert', NULL, '', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Tools & more'), NULL, 'https://swim.triathlon-coaching.com', 'Schwimmtraining & -pläne', 0, true, true);
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Tools & more'), NULL, 'https://roadtokona.triathlon-coaching.com', '#roadtokona', 1, true, true);
diff --git a/db/articles/006_kontakt.sql b/db/articles/006_kontakt.sql
new file mode 100644 (file)
index 0000000..7dc4a8e
--- /dev/null
@@ -0,0 +1,6 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'kontakt', NULL, 'contact', 5, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, NULL, (SELECT id FROM :"schema".pages WHERE slug='kontakt'), NULL, 'Kontakt', 5, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='kontakt'), 1, NULL, 'Kontakt', 'Schreib mir – ich melde mich asap.', 'Kontakt', NULL, '', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/007_impressum.sql b/db/articles/007_impressum.sql
new file mode 100644 (file)
index 0000000..f8bcd17
--- /dev/null
@@ -0,0 +1,11 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'impressum', NULL, 'legal', 6, false, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='impressum'), 1, NULL, 'Impressum', NULL, NULL, NULL, 'Ole B. Rosentreter  
+Fürther Straße 59  
+90513 Zirndorf  
++49 / 911 / 45 05 73 79  
+[www.triathlon-coaching.com/kontakt](https://www.triathlon-coaching.com/kontakt)  
+
+Quelle: [http://www.e-recht24.de](http://www.e-recht24.de/impressum-generator.html)', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/008_datenschutz.sql b/db/articles/008_datenschutz.sql
new file mode 100644 (file)
index 0000000..dd94622
--- /dev/null
@@ -0,0 +1,133 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'datenschutz', NULL, 'legal', 7, false, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='datenschutz'), 1, NULL, 'Datenschutz', NULL, NULL, NULL, '## Disclaimer / Haftung / Urheberrecht
+
+### Haftung für Inhalte
+
+Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.
+
+### Haftung für Links
+
+Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
+
+### Urheberrecht
+
+Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
+
+Quellenangaben: [Disclaimer](http://www.e-recht24.de/muster-disclaimer.html) von eRecht24, dem Portal zum Internetrecht von Rechtsanwalt Sören Siebert, [eRecht24 Disclaimer](http://www.e-recht24.de/muster-disclaimer.html)
+
+## Datenschutz
+
+### Datenschutzerklärung
+
+#### Datenschutzbeauftragter
+
+Verantwortliche Stelle im Sinne der Datenschutzgesetze, insbesondere der EU-Datenschutzgrundverordnung (DSGVO), ist:
+
+Ole B. Rosentreter
+
+#### Ihre Betroffenenrechte
+
+Unter den angegebenen Kontaktdaten unseres Datenschutzbeauftragten können Sie jederzeit folgende Rechte ausüben:
+
+- Auskunft über Ihre bei uns gespeicherten Daten und deren Verarbeitung
+- Berichtigung unrichtiger personenbezogener Daten
+- Löschung Ihrer bei uns gespeicherten Daten
+- Einschränkung der Datenverarbeitung, sofern wir Ihre Daten aufgrund gesetzlicher Pflichten noch nicht löschen dürfen
+- Widerspruch gegen die Verarbeitung Ihrer Daten bei uns
+- Datenübertragbarkeit, sofern Sie in die Datenverarbeitung eingewilligt haben oder einen Vertrag mit uns abgeschlossen haben
+
+Sofern Sie uns eine Einwilligung erteilt haben, können Sie diese jederzeit mit Wirkung für die Zukunft widerrufen.
+
+Sie können sich jederzeit mit einer Beschwerde an die für Sie zuständige Aufsichtsbehörde wenden. Ihre zuständige Aufsichtsbehörde richtet sich nach dem Bundesland Ihres Wohnsitzes, Ihrer Arbeit oder der mutmaßlichen Verletzung. Eine Liste der Aufsichtsbehörden (für den nichtöffentlichen Bereich) mit Anschrift finden Sie unter:  
+<https://www.bfdi.bund.de/DE/Infothek/Anschriften_Links/anschriften_links-node.html>.
+
+#### Zwecke der Datenverarbeitung durch die verantwortliche Stelle und Dritte
+
+Wir verarbeiten Ihre personenbezogenen Daten nur zu den in dieser Datenschutzerklärung genannten Zwecken. Eine Übermittlung Ihrer persönlichen Daten an Dritte zu anderen als den genannten Zwecken findet nicht statt. Wir geben Ihre persönlichen Daten nur an Dritte weiter, wenn:
+
+- Sie Ihre ausdrückliche Einwilligung dazu erteilt haben,
+- die Verarbeitung zur Abwicklung eines Vertrags mit Ihnen erforderlich ist,
+- die Verarbeitung zur Erfüllung einer rechtlichen Verpflichtung erforderlich ist,
+- die Verarbeitung zur Wahrung berechtigter Interessen erforderlich ist und kein Grund zur Annahme besteht, dass Sie ein überwiegendes schutzwürdiges Interesse an der Nichtweitergabe Ihrer Daten haben.
+
+#### Löschung bzw. Sperrung der Daten
+
+Wir halten uns an die Grundsätze der Datenvermeidung und Datensparsamkeit. Wir speichern Ihre personenbezogenen Daten daher nur so lange, wie dies zur Erreichung der hier genannten Zwecke erforderlich ist oder wie es die vom Gesetzgeber vorgesehenen vielfältigen Speicherfristen vorsehen. Nach Fortfall des jeweiligen Zweckes bzw. Ablauf dieser Fristen werden die entsprechenden Daten routinemäßig und entsprechend den gesetzlichen Vorschriften gesperrt oder gelöscht.
+
+#### Erfassung allgemeiner Informationen beim Besuch unserer Website
+
+Wenn Sie auf unsere Website zugreifen, werden automatisch mittels eines Cookies Informationen allgemeiner Natur erfasst. Diese Informationen (Server-Logfiles) beinhalten etwa die Art des Webbrowsers, das verwendete Betriebssystem, den Domainnamen Ihres Internet-Service-Providers und ähnliches. Hierbei handelt es sich ausschließlich um Informationen, welche keine Rückschlüsse auf Ihre Person zulassen.
+
+Diese Informationen sind technisch notwendig, um von Ihnen angeforderte Inhalte von Webseiten korrekt auszuliefern und fallen bei Nutzung des Internets zwingend an. Sie werden insbesondere zu folgenden Zwecken verarbeitet:
+
+- Sicherstellung eines problemlosen Verbindungsaufbaus der Website
+- Sicherstellung einer reibungslosen Nutzung unserer Website
+- Auswertung der Systemsicherheit und -stabilität
+- weitere administrative Zwecke
+
+Die Verarbeitung Ihrer personenbezogenen Daten basiert auf unserem berechtigten Interesse aus den vorgenannten Zwecken zur Datenerhebung. Wir verwenden Ihre Daten nicht, um Rückschlüsse auf Ihre Person zu ziehen. Empfänger der Daten sind nur die verantwortliche Stelle und ggf. Auftragsverarbeiter.
+
+Anonyme Informationen dieser Art werden von uns gegebenenfalls statistisch ausgewertet, um unseren Internetauftritt und die dahinterstehende Technik zu optimieren.
+
+#### Cookies
+
+Wie viele andere Webseiten verwenden wir auch so genannte Cookies. Cookies sind kleine Textdateien, die von einem Websiteserver auf Ihre Festplatte übertragen werden. Hierdurch erhalten wir automatisch bestimmte Daten wie z. B. IP-Adresse, verwendeter Browser, Betriebssystem und Ihre Verbindung zum Internet.
+
+Cookies können nicht verwendet werden, um Programme zu starten oder Viren auf einen Computer zu übertragen. Anhand der in Cookies enthaltenen Informationen können wir Ihnen die Navigation erleichtern und die korrekte Anzeige unserer Webseiten ermöglichen.
+
+In keinem Fall werden die von uns erfassten Daten an Dritte weitergegeben oder ohne Ihre Einwilligung eine Verknüpfung mit personenbezogenen Daten hergestellt.
+
+Natürlich können Sie unsere Website grundsätzlich auch ohne Cookies betrachten. Internet-Browser sind regelmäßig so eingestellt, dass sie Cookies akzeptieren. Im Allgemeinen können Sie die Verwendung von Cookies jederzeit über die Einstellungen Ihres Browsers deaktivieren. Bitte verwenden Sie die Hilfefunktionen Ihres Internetbrowsers, um zu erfahren, wie Sie diese Einstellungen ändern können. Bitte beachten Sie, dass einzelne Funktionen unserer Website möglicherweise nicht funktionieren, wenn Sie die Verwendung von Cookies deaktiviert haben.
+
+#### SSL-Verschlüsselung
+
+Um die Sicherheit Ihrer Daten bei der Übertragung zu schützen, verwenden wir dem aktuellen Stand der Technik entsprechende Verschlüsselungsverfahren (z. B. SSL) über HTTPS.
+
+#### Kontaktformular
+
+Treten Sie bezüglich Fragen jeglicher Art per E-Mail oder Kontaktformular mit uns in Kontakt, erteilen Sie uns zum Zwecke der Kontaktaufnahme Ihre freiwillige Einwilligung. Hierfür ist die Angabe einer validen E-Mail-Adresse erforderlich. Diese dient der Zuordnung der Anfrage und der anschließenden Beantwortung derselben. Die Angabe weiterer Daten ist optional. Die von Ihnen gemachten Angaben werden zum Zwecke der Bearbeitung der Anfrage sowie für mögliche Anschlussfragen gespeichert. Nach Erledigung der von Ihnen gestellten Anfrage werden personenbezogene Daten automatisch gelöscht.
+
+#### Verwendung von Google Maps
+
+Diese Webseite verwendet Google Maps API, um geographische Informationen visuell darzustellen. Bei der Nutzung von Google Maps werden von Google auch Daten über die Nutzung der Kartenfunktionen durch Besucher erhoben, verarbeitet und genutzt. Nähere Informationen über die Datenverarbeitung durch Google können Sie den [Google-Datenschutzhinweisen](http://www.google.com/privacypolicy.html) entnehmen. Dort können Sie im Datenschutzcenter auch Ihre persönlichen Datenschutz-Einstellungen verändern.
+
+Ausführliche Anleitungen zur Verwaltung der eigenen Daten im Zusammenhang mit Google-Produkten finden Sie hier: <http://www.dataliberation.org/>.
+
+#### Eingebettete YouTube-Videos
+
+Auf einigen unserer Webseiten betten wir YouTube-Videos ein. Betreiber der entsprechenden Plugins ist die YouTube, LLC, 901 Cherry Ave., San Bruno, CA 94066, USA. Wenn Sie eine Seite mit dem YouTube-Plugin besuchen, wird eine Verbindung zu Servern von YouTube hergestellt. Dabei wird YouTube mitgeteilt, welche Seiten Sie besuchen. Wenn Sie in Ihrem YouTube-Account eingeloggt sind, kann YouTube Ihr Surfverhalten Ihnen persönlich zuordnen. Dies verhindern Sie, indem Sie sich vorher aus Ihrem YouTube-Account ausloggen.
+
+Wird ein YouTube-Video gestartet, setzt der Anbieter Cookies ein, die Hinweise über das Nutzerverhalten sammeln.
+
+Wer das Speichern von Cookies für das Google-Ad-Programm deaktiviert hat, wird auch beim Anschauen von YouTube-Videos mit keinen solchen Cookies rechnen müssen. YouTube legt aber auch in anderen Cookies nicht-personenbezogene Nutzungsinformationen ab. Möchten Sie dies verhindern, so müssen Sie das Speichern von Cookies im Browser blockieren.
+
+Weitere Informationen zum Datenschutz bei YouTube finden Sie in der Datenschutzerklärung des Anbieters unter:  
+<https://www.google.de/intl/de/policies/privacy/>
+
+#### Social Plugins
+
+Auf unseren Webseiten werden Social Plugins der unten aufgeführten Anbieter eingesetzt. Die Plugins können Sie daran erkennen, dass sie mit dem entsprechenden Logo gekennzeichnet sind.
+
+Über diese Plugins werden unter Umständen Informationen, zu denen auch personenbezogene Daten gehören können, an den Dienstebetreiber gesendet und ggf. von diesem genutzt. Wir verhindern die unbewusste und ungewollte Erfassung und Übertragung von Daten an den Diensteanbieter durch eine 2-Klick-Lösung. Um ein gewünschtes Social Plugin zu aktivieren, muss dieses erst durch Klick auf den entsprechenden Schalter aktiviert werden. Erst durch diese Aktivierung des Plugins wird auch die Erfassung von Informationen und deren Übertragung an den Diensteanbieter ausgelöst. Wir erfassen selbst keine personenbezogenen Daten mittels der Social Plugins oder über deren Nutzung.
+
+Wir haben keinen Einfluss darauf, welche Daten ein aktiviertes Plugin erfasst und wie diese durch den Anbieter verwendet werden. Derzeit muss davon ausgegangen werden, dass eine direkte Verbindung zu den Diensten des Anbieters aufgebaut wird sowie mindestens die IP-Adresse und gerätebezogene Informationen erfasst und genutzt werden. Ebenfalls besteht die Möglichkeit, dass die Diensteanbieter versuchen, Cookies auf dem verwendeten Rechner zu speichern. Welche konkreten Daten hierbei erfasst und wie diese genutzt werden, entnehmen Sie bitte den Datenschutzhinweisen des jeweiligen Diensteanbieters. Hinweis: Falls Sie zeitgleich bei Facebook angemeldet sind, kann Facebook Sie als Besucher einer bestimmten Seite identifizieren.
+
+Wir haben auf unserer Website die Social-Media-Buttons folgender Unternehmen eingebunden:
+
+*(Auflistung der konkreten Anbieter kann hier ergänzt werden.)*
+
+#### Änderung unserer Datenschutzbestimmungen
+
+Wir behalten uns vor, diese Datenschutzerklärung anzupassen, damit sie stets den aktuellen rechtlichen Anforderungen entspricht oder um Änderungen unserer Leistungen in der Datenschutzerklärung umzusetzen, z. B. bei der Einführung neuer Services. Für Ihren erneuten Besuch gilt dann die neue Datenschutzerklärung.
+
+#### Fragen an den Datenschutzbeauftragten
+
+Wenn Sie Fragen zum Datenschutz haben, schreiben Sie uns bitte eine E-Mail oder wenden Sie sich direkt an die für den Datenschutz verantwortliche Person in unserer Organisation:
+
+Ole B. Rosentreter  
+[datenschutz@laktatnebel.de](mailto:datenschutz@laktatnebel.de)
+
+Die Datenschutzerklärung wurde mit dem [Datenschutzerklärungs-Generator der activeMind AG erstellt](https://www.activemind.de/datenschutz/datenschutzhinweis-generator/).', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/009_agb.sql b/db/articles/009_agb.sql
new file mode 100644 (file)
index 0000000..6cb6e7e
--- /dev/null
@@ -0,0 +1,87 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'agb', NULL, 'legal', 8, false, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='agb'), 1, NULL, 'AGB', NULL, NULL, NULL, '## Bedingungen für Kurse
+
+1. **Anmeldung**  
+   Die Kursanmeldung erfolgt nur schriftlich oder online in Form des Anmeldeformulars. Der vom Athleten gewünschte Kursplatz wird von triathlon-coaching.com bei zeitgerechter Zahlung der anfallenden Kursgebühren zugesichert. triathlon-coaching.com behält sich vor, den Kursplatz bei nicht zeitgerechter Zahlung der Gebühr weiterzuvergeben. Anmeldungen werden in der Reihenfolge Ihres Eingangs berücksichtigt. triathlon-coaching.com benachrichtigt Sie, wenn der Kurs belegt ist oder nicht stattfindet. Der Kurs findet nur bei der bekanntgegebenen Mindestteilnehmerzahl statt.
+
+2. **Kosten**  
+   Die Kosten pro Kurs entnehmen Sie aus dem Anmeldeformular. Die Bezahlung muss vor Kursbeginn erfolgen.
+
+3. **Kostenerstattung**  
+   Die Rückzahlung der Kursgebühr ist nur möglich, sollte der Kurs die Mindestteilnehmerzahl nicht erreichen und somit nicht stattfinden. Sollte ein Kursteilnehmer an einer Stunde nicht teilnehmen können, kann diese nicht nachgeholt oder die Gebühr zurückerstattet werden. Kommt es zu einem Ausfall aufgrund einer Verhinderung des Kursleiters, erfolgt eine anteilige Rückzahlung. Es ist nicht möglich, Nachholstunden in Anspruch zu nehmen.
+
+4. **Haftung**  
+   Jeder Teilnehmer trägt selbst das Risiko eines Personen- oder Sachschadens aus seiner Kursteilnahme. triathlon-coaching.com empfiehlt jedem Kursteilnehmer, sich vor Belegung der Kurse im Hinblick auf die Teilnahme an Kursen und des angebotenen Trainingsprogramms ärztlich untersuchen und beraten zu lassen. Bestehende, dem Kursteilnehmer bekannte Krankheiten oder Leiden, die bestimmte Bewegungen und/oder körperliche Aktivitäten problematisch oder gar gefährlich werden lassen können, sind triathlon-coaching.com bzw. dem jeweiligen Trainer vor Kursbeginn bzw. der jeweiligen Trainingseinheit unaufgefordert mitzuteilen. Eine Haftung für persönliche Gegenstände, die während der Veranstaltung verloren gehen oder beschädigt werden, besteht nicht.
+
+5. **Kursänderungen**  
+   Kurszusammenlegungen, Kursänderungen und personelle Umbesetzungen behalte ich mir vor. Ein Anspruch auf Unterricht durch bestimmte Kursleiter besteht nicht. Änderungen werden, soweit erforderlich, mitgeteilt.
+
+6. **Datenschutz**  
+   Es wird darauf hingewiesen, dass die Firma triathlon-coaching.com das Bundesdatenschutzgesetz einhält und gem. § 28 BDSG die Erhebung, Verarbeitung und Nutzung personenbezogener Daten ausschließlich für eigene Zwecke vornimmt sowie Daten nur für den Zweck erhebt, für den sie auch genutzt werden. Teilnehmerdaten werden von triathlon-coaching.com nicht an Dritte weitergegeben. In allen Kursen werden fotografische Aufnahmen (Fotos und Videos) von den Teilnehmern während des Trainings gemacht und ggf. zu Werbezwecken auf der Homepage oder in sozialen Netzwerken veröffentlicht. Der Teilnehmer hat das Recht, dies zu verweigern. Um entsprechenden Hinweis, der schriftlich zu erfolgen hat, wird vor Campbeginn gebeten.
+
+7. **Salvatorische Klausel**  
+   Mündliche Nebenabreden sind nicht gültig. Sollte eine Bestimmung der Allgemeinen Kursbedingungen unwirksam sein, wird die Wirksamkeit der übrigen Bestimmungen davon nicht berührt.
+
+---
+
+## Bedingungen für Coaching
+
+1. **Bestellung und Lieferung**  
+   Die Bestellung erfolgt nur schriftlich oder online in Form des Anmeldeformulars und/oder nach einem Erstgespräch. Der somit vom Athleten gewünschte Trainingsplan wird von triathlon-coaching.com erstellt. Der erste Trainingsplan wird mindestens einen Tag vor Beginn des Trainings per E-Mail zugestellt bzw. über Trainingpeaks freigegeben. Sofern nicht anders vereinbart, ist der Trainingsbeginn am ersten Montag, spätestens aber am 10. Kalendertag nach Eingang der Bestellung.
+
+2. **Kosten und Zahlung**  
+   Mit Erhalt des Trainingsplans wird die Gebühr fällig. Das Erstgespräch ist kostenfrei.
+
+3. **Kostenerstattung**  
+   Die Rückzahlung der Gebühr für den Trainingsplan ist nur möglich, wenn durch Verschulden von triathlon-coaching.com der Trainingsplan zu spät zugestellt wurde.
+
+4. **Haftung**  
+   Jeder Athlet trägt selbst das Risiko eines Personen- oder Sachschadens aus seinem Training und den Anweisungen aus dem Trainingsplan. triathlon-coaching.com empfiehlt jedem Athleten, sich vor Bestellung eines Trainingsplans im Hinblick auf das zu absolvierende Trainingsprogramm ärztlich untersuchen und beraten zu lassen. Bestehende, dem Athleten bekannte Krankheiten oder Leiden, die bestimmte Bewegungen und/oder körperliche Aktivitäten problematisch oder gar gefährlich werden lassen können, sind triathlon-coaching.com vor Bestellung unaufgefordert mitzuteilen. Eine Übernahme der Haftung durch triathlon-coaching.com erfolgt daraus nicht.
+
+5. **Datenschutz**  
+   Es wird darauf hingewiesen, dass die Firma triathlon-coaching.com das Bundesdatenschutzgesetz einhält und gem. § 28 BDSG die Erhebung, Verarbeitung und Nutzung personenbezogener Daten ausschließlich für eigene Zwecke vornimmt sowie Daten nur für den Zweck erhebt, für den sie auch genutzt werden. Kundendaten werden von triathlon-coaching.com nicht an Dritte weitergegeben.
+
+6. **Salvatorische Klausel**  
+   Mündliche Nebenabreden sind nicht gültig. Sollte eine Bestimmung der Allgemeinen Bedingungen unwirksam sein, wird die Wirksamkeit der übrigen Bestimmungen davon nicht berührt.
+
+---
+
+## Bedingungen für Camps
+
+1. **Anmeldung**  
+   Die schriftliche Anmeldung des Sportpaketes kann über die Homepage direkt oder per E-Mail erfolgen. Mit der Anmeldung bietet der Teilnehmer triathlon-coaching.com den Abschluss des Vertrages verbindlich an und bestätigt damit die Kenntnisnahme und Einwilligung der allgemeinen Geschäftsbedingungen. An die Buchung ist der Teilnehmer 5 Werktage gebunden. Der Vertrag kommt mit dem Zugang der Buchungsbestätigung (Annahmeerklärung) durch triathlon-coaching.com per E-Mail, E-Mail-Anhang, Post oder Fax zustande. Die Übermittlung des Vertragsangebots durch Betätigung des Buttons „verbindlich buchen“ begründet keinen Anspruch des Teilnehmers auf das Zustandekommen eines Teilnahmevertrags entsprechend seiner Buchungsangaben. triathlon-coaching.com ist vielmehr frei in der Entscheidung, das Vertragsangebot des Teilnehmers anzunehmen oder nicht.
+
+2. **Bezahlung**  
+   Bei Anmeldung wird eine Anzahlung in Höhe von 25 % des ausgeschriebenen Preises fällig, mindestens jedoch 100 Euro. Die Restzahlung ist 21 Tage vor Reisebeginn zahlbar. Leistet der Teilnehmer die Anzahlung und/oder die Restzahlung nicht entsprechend den vereinbarten Zahlungsfälligkeiten, so ist triathlon-coaching.com berechtigt, nach Mahnung mit Fristsetzung vom Vertrag zurückzutreten und den Teilnehmer mit Rücktrittskosten gemäß Ziffer 3 zu belasten.
+
+3. **Rücktritt / Stornokosten / Umbuchung**  
+   Der Teilnehmer kann jederzeit vom Sportpaket zurücktreten. Der Rücktritt ist gegenüber triathlon-coaching.com stets in schriftlicher Form zu erklären. triathlon-coaching.com kann, soweit dem Rücktritt kein Fall höherer Gewalt vorliegt, eine angemessene Entschädigung für die bis zum Rücktritt getroffenen Vorbereitungen und Aufwendungen von dem jeweiligen Preis verlangen. Die Entschädigung wird nach dem Zeitpunkt des Zugangs der Rücktrittserklärung wie folgt berechnet:  
+   Bis 30 Tage vor Beginn 25 % des Preises,  
+   29–15 Tage vor Beginn 50 % des Preises,  
+   14–7 Tage vor Beginn 75 % des Preises,  
+   6–0 Tage vor Beginn 100 % des Preises, jedoch nicht mehr als bereits geleistete Zahlungen.  
+   Das gesetzliche Recht des Teilnehmers, gemäß § 651 b BGB einen Ersatzteilnehmer zu stellen, bleibt durch die vorstehenden Bedingungen unberührt. Die in diesem Falle fällige Umbuchungsgebühr beträgt 50 Euro pro Person.
+
+4. **Mindestteilnehmerzahl**  
+   triathlon-coaching.com kann wegen Nichterreichens der Mindestteilnehmerzahl vom Vertrag zurücktreten, wenn in der jeweiligen Ausschreibung die Mindestteilnehmerzahl beziffert ist. Ein Rücktritt ist spätestens am ausgeschriebenen Zeitpunkt dem Teilnehmer gegenüber zu erklären. Sollte bereits zu einem früheren Zeitpunkt ersichtlich sein, dass die Mindestteilnehmerzahl nicht erreicht werden kann, hat triathlon-coaching.com unverzüglich von seinem Rücktrittsrecht Gebrauch zu machen. Wird das Camp aus diesem Grund nicht durchgeführt, erhält der Teilnehmer bereits geleistete Zahlungen unverzüglich und ohne Abzüge zurück. Ein Rücktritt von triathlon-coaching.com später als 30 Tage vor Reisebeginn ist unzulässig. Der Teilnehmer wird darauf hingewiesen, dass ihn eine Absage der Reise durch triathlon-coaching.com wegen Nichterreichens der Mindestteilnehmerzahl nicht zum kostenfreien Rücktritt gegenüber Fluggesellschaften, Beherbergungsunternehmern oder anderen Touristikunternehmen berechtigt, bei denen er Flüge oder andere Dienstleistungen für die Reise gebucht hat. Dem Teilnehmer wird empfohlen, soweit möglich Flugtarife und Dienstleistungen zu buchen, die ihn im Falle einer Absage zu einer kostengünstigen Stornierung berechtigen.
+
+5. **Kündigung aus verhaltensbedingten Gründen**  
+   triathlon-coaching.com behält sich das Recht vor, einem Teilnehmer während eines laufenden Camps ohne Einhaltung einer Frist zu kündigen, wenn der Teilnehmer ungeachtet einer Abmahnung von triathlon-coaching.com die Gruppe nachhaltig und vorsätzlich stört oder wenn er sich in solchem Maße vertragswidrig verhält, dass die sofortige Aufhebung des Vertrages gerechtfertigt ist. Eine Rückerstattung des gezahlten Camp-Preises ist in diesem Falle ausgeschlossen.
+
+6. **Beschränkung der Haftung**  
+   Die Teilnahme an jeglichen Sportpaketen von triathlon-coaching.com geschieht ausdrücklich auf eigene Verantwortung. Der Teilnehmer bestätigt triathlon-coaching.com bei Zustandekommen des Vertrages seine körperliche Unversehrtheit und Tauglichkeit für die angebotenen sportlichen Aktivitäten und verpflichtet sich, einen Haftungsausschluss zu unterzeichnen. triathlon-coaching.com empfiehlt Personen eine sportärztliche Untersuchung vor Buchung und Antritt eines Trainingscamps. triathlon-coaching.com übernimmt keine Haftung für etwaige Schäden oder Verluste jeglicher Art. Alle Teilnehmer üben ihren Sport auf eigenes Risiko aus. Für Unfälle und körperliche Schäden, die aus der Ausübung des Sportes, insbesondere des Radsports, herrühren, haftet triathlon-coaching.com in keinem Falle, auch dann nicht, wenn der Teilnehmer in einer Gruppe mit Gruppenleitung fährt. Bei triathlon-coaching.com ist das Tragen eines Helmes Voraussetzung zum Fahren in der Gruppe. Für die Einhaltung der Straßenverkehrsvorschriften ist jeder Teilnehmer selbst verantwortlich, auch dann, wenn in einer Gruppe gefahren wird. triathlon-coaching.com empfiehlt, für einen ergänzenden Versicherungsschutz zu sorgen, wie z. B. Reisegepäckversicherung, Reiseunfall- und Reisekrankenversicherung sowie Extra-Rückreisekostenversicherung.
+
+7. **Nicht in Anspruch genommene Leistung**  
+   Nimmt der Teilnehmer einzelne Reiseleistungen, die ihm ordnungsgemäß angeboten wurden, nicht in Anspruch aus Gründen, die ihm zuzurechnen sind (z. B. wegen vorzeitiger Rückreise oder aus sonstigen zwingenden Gründen), hat er keinen Anspruch auf anteilige Erstattung des Reisepreises.
+
+8. **Datenschutz**  
+   Es wird darauf hingewiesen, dass die Firma triathlon-coaching.com das Bundesdatenschutzgesetz einhält und gem. § 28 BDSG die Erhebung, Verarbeitung und Nutzung personenbezogener Daten ausschließlich für eigene Zwecke vornimmt sowie Daten nur für den Zweck erhebt, für den sie auch genutzt werden. Teilnehmerdaten werden von triathlon-coaching.com nicht an Dritte weitergegeben. In allen Camps werden fotografische Aufnahmen (Fotos und Videos) von den Teilnehmern während des Trainings gemacht und ggf. zu Werbezwecken auf der Homepage oder in sozialen Netzwerken veröffentlicht. Der Teilnehmer hat das Recht, dies zu verweigern. Um entsprechenden Hinweis, der schriftlich zu erfolgen hat, wird vor Campbeginn gebeten.
+
+9. **Rechtswahl- und Gerichtsstand**  
+   Für Teilnehmer, die nicht Angehörige eines Mitgliedstaats der Europäischen Union sind, gilt für das gesamte Rechts- und Vertragsverhältnis zwischen dem Teilnehmer und triathlon-coaching.com ausschließlich deutsches Recht. Als Gerichtsstand wird Nürnberg vereinbart.
+
+10. **Salvatorische Klausel**  
+    Mündliche Nebenabreden sind nicht gültig. Sollte eine Bestimmung der Allgemeinen Bedingungen unwirksam sein, wird die Wirksamkeit der übrigen Bestimmungen davon nicht berührt.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/010_personal-coaching.sql b/db/articles/010_personal-coaching.sql
new file mode 100644 (file)
index 0000000..e67b237
--- /dev/null
@@ -0,0 +1,7 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'personal-coaching', (SELECT id FROM :"schema".pages WHERE slug='coaching'), 'category-grid', 0, true, 'angebot', NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Coaching'),
+                                                          (SELECT id FROM :"schema".pages WHERE slug='personal-coaching'), NULL, 'Personal Coaching', 0, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='personal-coaching'), 1, NULL, 'Personal Coaching', 'Was steckt drin, was kostet es – und was nicht.', 'Angebot', NULL, '', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/011_standard-plaene.sql b/db/articles/011_standard-plaene.sql
new file mode 100644 (file)
index 0000000..83cf7e0
--- /dev/null
@@ -0,0 +1,49 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'standard-plaene', (SELECT id FROM :"schema".pages WHERE slug='coaching'), 'content-page', 1, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Coaching'),
+                                                          (SELECT id FROM :"schema".pages WHERE slug='standard-plaene'), NULL, 'Standard-Pläne', 1, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='standard-plaene'), 1, NULL, 'Standard-Pläne', 'Strukturierte Trainingspläne für alle Distanzen.', 'Angebot', NULL, '## Training von der Stange
+
+Wenn Dir Personal Coaching aus welchen Gründen auch immer nicht zusagt, sollst Du nicht im Regen stehen.
+
+Du kannst bei TrainingPeaks unter  
+[www.trainingpeaks.com/my-training-plans/triathlon-coaching.com](https://www.trainingpeaks.com/my-training-plans/triathlon-coaching.com)  
+Pläne für verschiedene Leistungsstufen kaufen und in Deinen TrainingPeaks-Account laden. Den brauchst Du allerdings, jedoch ist die Premium-Version nicht notwendig.
+
+Es gibt für jede Distanz 7 Leistungsstufen und 3 Distanzen von Kurzdistanz (1,5–40–10), Mitteldistanz/70.3 und Langdistanz. [Einschätzen](https://www.triathlon-coaching.com/blog/ziele-setzen-aber-richtig) musst Du Dich selbst.
+
+Die Saison wird in Trainingsphasen unterteilt:
+
+- Grundlagenphasen  
+  - Base 1 (online)  
+  - Base 2  
+  - Base 3  
+- Aufbauphasen  
+  - Build 1  
+  - Build 2  
+- Tapering  
+
+Somit gibt es für jede Stufe, Strecke und Phase einen Plan.
+
+Ein paar Anmerkungen:
+
+- Die Grundlagenphasen können wiederholt werden, es empfiehlt sich sogar. Auch die Aufbauphase Build 1 kann man zweimal ausführen. Build 2 möchtest Du nicht zweimal machen. ;-)
+- Auch wenn die Pläne im 3:1-Rhythmus – 3 Belastungswochen, 1 Adaptions-(Entlastungs)woche – aufgebaut sind, kannst Du 1 Woche rausnehmen, wenn es Dir aufgrund von Wettkämpfen besser passt.
+- Anstelle der Tests in der letzten Woche können auch Wettkämpfe eingebaut werden. Ansonsten bin ich ein Freund regelmäßiger Überprüfung des Fortschritts.
+
+Grundsätzliche Fragen dürfen gestellt werden:  
+[Schreibe mir eine Nachricht](https://www.triathlon-coaching.com/kontakt)
+
+Anmerkung zu den Zeiten: Die sind gedacht für die AK bis ca. AK 45, danach muss man naturgemäß altersbedingt Abstriche machen.  
+Und es kann auch schneller oder langsamer werden, abhängig von Wetter, Streckenprofil, Trainingsalter, Talent, Material ...
+
+## Die Pläne
+
+[Langdistanz-Pläne](https://www.triathlon-coaching.com/langdistanz)  
+
+[Mitteldistanz-Pläne](https://www.triathlon-coaching.com/mitteldistanz)  
+
+[Kurzdistanz-Pläne](https://www.triathlon-coaching.com/kurzdistanz)
+', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/012_langdistanz.sql b/db/articles/012_langdistanz.sql
new file mode 100644 (file)
index 0000000..f8771e0
--- /dev/null
@@ -0,0 +1,52 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'langdistanz', (SELECT id FROM :"schema".pages WHERE slug='standard-plaene'), 'content-page', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Standard-Pläne'),
+                                                          (SELECT id FROM :"schema".pages WHERE slug='langdistanz'), NULL, 'Langdistanz & Ironman', 0, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='langdistanz'), 1, NULL, 'Langdistanz & Ironman', NULL, 'Standard-Pläne', NULL, '## Langdistanz / Ironman
+
+### finisher
+
+Du willst eine Langdistanz finishen – nicht mehr und nicht weniger. Dein Ziel ist der rote Teppich und die 4 magischen Worte: You are an iron(wo)maaaaan!  
+Gleich vorneweg: Dein Training ist auf Kante genäht, bei weniger Training wird es eng mit dem Finish.  
+Zielzeit  bis 13 :00 (m) / 14:00 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-512198/base-1-full-distance-finisher)
+
+### good finisher
+
+Dein Langdistanz-Finish ist soll safe über die Bühne gehen. Mit unter 13 Stunden ist es wahrscheinlich noch hell, wenn Du im Ziel bist.  
+Zielzeit  12:00-13 :00 (m) / 13:00-14:00 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-512197/base-1-full-distance-good-finisher)
+
+### advanced finisher
+
+Du willst eine Langdistanz nicht nur irgendwie finishen, sondern souverän und ohne großes Wenn und Aber. Du bist nicht schnell, aber stabil unterwegs zu einem ungefährdeten Finish.  
+Zielzeit  ca. 11 30 (m) / 12 30 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-512194/base-1-full-distance-advanced-finisher)
+
+### hero
+
+Du schaffst es Familie, Job, Verpflichtungen und Training unter einen Hut zu bringen. Der Sport ist nicht wirklich die allererste Priorität, aber Du weißt welche Key-Sessions Du dann wirklich machen musst.  
+Dein Langdistanz-Finish ist im soliden Mittelfeld, Du kannst das Rennen genießen und Du kannst stolz auf Dich sein. Für Dein Umfeld bist Du eben ein: Held!  
+Zielzeit ca 11:00 (m) / 12 :00 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-511774/base-1-full-distance-hero)
+
+### club hero
+
+Im Verein zählst Du zu den Guten, gemeinsame Ausfahrten fährst Du fast komplett im Wind und Du kannst bei noch stärkeren fast mittrainieren. Für eine Langdistanz brauchst Du 10 (Mann) oder 11 (Frau) Stunden – plus minus.  
+Zielzeit ca 10:00 (m) / 11 :00 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-511434/base-1-full-distance-club-hero)
+
+### local hero
+
+In Deiner Gegend hat Dich Deine Konkurrenz auf dem Zettel. Du weißt, wo das Podium steht und wartest deshalb immer bis zur Siegerehrung. Die Quali für Hawaii ist noch eine halbe Nummer zu groß oder mit Glück beim richtigen Rennen erreichbar.  
+Zielzeit ca 9:15 (m) / 10:15 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-511290/base-1-full-distance-local-hero)
+
+### qualifier
+
+Als Qualifier kommst Du bereit, gesund und mit einer gewissen Grundfitness aus der Off-Season. Dein Ziel ist die  
+Insel, also die Quali für Hawaii. Du bist willens, Dich vom ersten Moment an zu schinden und bestehst mental nur aus dem einen Ziel.  
+Zielzeit unter 8:45 (m) / 9:30 (w)  
+[Link zum Plan (Base 1)](https://www.trainingpeaks.com/training-plans/triathlon/ironman/tp-511274/base-1-full-distance-kona-qualifier)', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/013_mitteldistanz.sql b/db/articles/013_mitteldistanz.sql
new file mode 100644 (file)
index 0000000..1d82306
--- /dev/null
@@ -0,0 +1,54 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'mitteldistanz', (SELECT id FROM :"schema".pages WHERE slug='standard-plaene'), 'content-page', 1, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Standard-Pläne'),
+                                                          (SELECT id FROM :"schema".pages WHERE slug='mitteldistanz'), NULL, 'Mitteldistanz & Ironman 70.3', 1, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='mitteldistanz'), 1, NULL, 'Mitteldistanz & Ironman 70.3', NULL, 'Standard-Pläne', NULL, '## Mitteldistanz / Ironman 70.3
+
+### finisher
+
+Du willst eine Mitteldistanz finishen – nicht mehr und nicht weniger. Dein Ziel ist es schlicht und ergreifend die doppelte Kurzdistanz zu bewältigen und Dein Siegerbierchen zu genießen. Zum Wohl!  
+Zielzeit bis 6:00 (m) / 6:30 (w)
+
+1. [Link zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-512297/base-1-half-distance-finisher)
+2. [Link zum Plan (Base 2)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-534712/base-2-1-half-distance-qualifier)
+
+### good finisher
+
+Deine Mitteldistanz ist für Dich Deine ganz persönliche Challenge und es irgendwie mit Hängen und Würgen zuschaffen ist nicht Dein Anspruch.  
+Zielzeit unter 6:00 (m) / 6:30 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-512298/base-1-half-distance-good-finisher)
+
+### advanced finisher
+
+Du willst eine 70.3 / Mitteldistanz nicht nur irgendwie finishen, sondern souverän und ohne großes Wenn und Aber. Die Langdistanz ist Dir zu viel und auf der Kurzdistanz siehst Du gegen die schnellen Hirsche kein Land. Du bist nicht schnell, aber stabil unterwegs zu einem ungefährdeten Finish.  
+Zielzeit ca 5:40 (m) / 6:10 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-512299/base-1-half-distance-advanced-finisher)
+
+### hero
+
+Du schaffst es Familie, Job, Verpflichtungen und Training unter einen Hut zu bringen. Der Sport ist nicht wirklich die allererste Priorität, aber Du weißt welche Key-Sessions Du dann wirklich machen musst.  
+Du landest bei allen Rennen im soliden Mittelfeld, Du kannst das Rennen genießen, und lässt so einige hinter Dir und bist stolz auf Dich.  
+Zielzeit ca 5:15 (m) / 5:45 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-512300/base-1-half-distance-hero)
+
+### club hero
+
+Im Verein zählst Du zu den Guten, gemeinsame Ausfahrten fährst Du fast komplett im Wind und Du kannst bei noch stärkeren fast mittrainieren. Bei einem 70.3 möchtest Du die 5:00 (Mann) oder 5:30 (Frau) Stunden unterbieten.  
+Die Langdistanz ist aktuell kein Thema für Dich.  
+Zielzeit ca 4:45 (m) / 5:15 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-511762/base-1-half-distance-club-hero)
+
+### local hero
+
+In Deiner Gegend hat Dich Deine Konkurrenz auf dem Zettel. Du weißt, wo das Podium steht und wartest deshalb immer bis zur Siegerehrung. Die Langdistanz ist für Dich Nebensache, aber machbar, auch wenn es zum Ende hin härter werden dürfte.  
+Zielzeit unter 4:30 (m) / 5:00 (w)  
+[Link zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-512295/base-1-half-distance-local-hero)
+
+### qualifier
+
+Als Qualifier kommst Du gesund und mit einer gewissen Grundfitness aus der Off-Season. Dein Ziel ist eine WM (70.3, Challenge …). „Dabei sein ist alles“ ist nice, aber Du startest da nicht, um Zweiter zu werden 😉 Und dafür bsit Du bereit, Dich vom ersten Moment an immer einen Tick mehr zu schinden als die Konkurrenz. Leide im Training, damit die anderen im Wettkampf leiden. Die Langdistanz ist für Dich mit einer sehr guten Zeit machbar, aber nicht Dein Hauptfokus.  
+Zielzeit unter 4:15 (m) / 4:45 (w)  
+[Link zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/half-ironman/tp-512296/base-1-half-distance-championchip-qualifier)
+', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/014_kurzdistanz.sql b/db/articles/014_kurzdistanz.sql
new file mode 100644 (file)
index 0000000..4111c14
--- /dev/null
@@ -0,0 +1,44 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'kurzdistanz', (SELECT id FROM :"schema".pages WHERE slug='standard-plaene'), 'content-page', 2, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".nav_items    VALUES (DEFAULT, (SELECT id FROM :"schema".nav_items WHERE label='Standard-Pläne'),
+                                                          (SELECT id FROM :"schema".pages WHERE slug='kurzdistanz'), NULL, 'Kurz- & olympische Distanz', 2, false, true);
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='kurzdistanz'), 1, NULL, 'Kurz- & olympische Distanz', NULL, 'Standard-Pläne', NULL, '## Kurz-/ olympische Distanz
+
+### finisher
+
+Du willst (mal) einen Triathlon finishen – nicht mehr und nicht weniger. Dein Ziel ist es schlicht und ergreifend eine Kurzdistanz wie bei Olympia zu bewältigen und Dich Triathlet nennen dürfen. Auch Dein Motto ist olympisch: Dabei sein ist alles!  
+Zielzeit bis 3:00 (m) / 3:20 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/olympic/tp-519355/base-1-olympic-distance-finisher)
+
+### good finisher
+
+Dein olypischer Triathlon ist für Dich Deine ganz persönliche Challenge und es irgendwie mit Hängen und Würgen zuschaffen ist nicht Dein Anspruch.  
+Zielzeit unter 3:00 (m) / 3:20 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/olympic/tp-519353/base-1-olympic-distance-good-finisher)
+
+### advanced finisher
+
+Du bist solide unterwegs und brauchst für die 1,5-40-10 nicht mehr als 2:45 (Mann) bzw. 3:00 (Frau) Stunden. Du kannst kannst alle 3 Disziplinen, ohne in einer wirklich glänzen zu müssen, oder Du bist ein Spezialist in einer und nimmst den Rest einfach mal so mit.  
+Zielzeit unter 2:45 (m) / 3:00 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/olympic/tp-519354/base-1-olympic-distance-advanced-finisher)
+
+### hero
+
+Du schaffst es Familie, Job, Verpflichtungen und Training unter einen Hut zu bringen. Der Sport ist nicht wirklich die allererste Priorität, aber Du weißt welche Key-Sessions Du dann wirklich machen musst.  
+Du landest bei allen Rennen im soliden Mittelfeld, Du kannst das Rennen genießen, und lässt so einige hinter Dir und bist stolz auf Dich.  
+Zielzeit unter 2:30 (m) / 2:45 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/olympic/tp-519352/base-1-olympic-distance-hero)
+
+### club hero
+
+Im Verein zählst Du zu den Guten in allen 3 Disziplinen, eine signifikante Schwäche hast Du nicht. Bei einem flachen „olympischen“ bist Du im Bereich 2:15 (Mann) oder 2:30 (Frau) Stunden unterwegs und zeigst damit den meisten die Hacken.  
+Zielzeit ca 2:15 (m) / 2:30 (w)  
+[Links zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/olympic/tp-519351/base-1-olympic-distance-club-hero)
+
+### local hero
+
+In Deiner Gegend hat Dich Deine Konkurrenz auf dem Zettel. Du weißt, wo das Podium steht und wartest deshalb immer bis zur Siegerehrung. Dein Fokus ist die Kurzdistanz, Du startest vielleicht auch in einem Ligateam. Du willst hart und schnell racen, auch auf kürzeren Distanzen.  
+Zielzeit unter 2:10 (m) / 2:25 (w)  
+[Link zum Plan (Base1)](https://www.trainingpeaks.com/training-plans/triathlon/olympic/tp-519328/base-1-olympic-distance-local-hero)', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
diff --git a/db/articles/015_blog_warum-einen-coach.sql b/db/articles/015_blog_warum-einen-coach.sql
new file mode 100644 (file)
index 0000000..7b7c902
--- /dev/null
@@ -0,0 +1,61 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/warum-einen-coach', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/warum-einen-coach'), 1, (SELECT id FROM :"schema".categories WHERE slug='coaching'), 'Warum einen Coach?', NULL, NULL, 'Natürlich geht alles auch ohne Coach. Ganz ohne Frage. Jedoch spart Dir ein Coach Zeit und kaufst professionelles Know-How ein.', '## Ich brauche keinen Coach.
+
+       Natürlich geht alles auch ohne Coach. Ganz ohne Frage.
+
+Einen Coach zu engagieren, hat nicht nur positive Aspekte. Erstens kostet er Geld und zweitens bedingt die Zusammenarbeit eine gewisse Öffnung der Privatsphäre. Wer das nicht möchte, greift besser zu einem Trainingsplan von der Stange. Oder coacht sich selbst.
+
+## Self-Coaching vs. Coach
+
+Wenn Du Dich selbst coachst – und da kann ich eigentlich schon aufhören zu schreiben.  
+„Selbst“ und „Coaching“ ist ein Widerspruch in sich. Wie kannst Du denn einen neutralen Standpunkt Dir selbt gegenüber einnehmen?
+
+Der andere Aspekt ist, dass Selbstcoaching eine Menge Wissen voraussetzt. So wie Du Dir für Steuern, Handwerk usw. einen Dienstleister engagierst, so engagierst Du Dir einen Coach für Dein Training. Ja, Du könnstes Deine Steuern auch selber machen …
+
+Mit einem Coach sparst Zeit und kaufst professionelles Know-How ein.
+
+## Trainingspläne vs. Coach
+
+Auch ich biete Pläne ohne Betreuung an, denn nicht jeder kann sich das leisten.
+
+Dennoch hat dieses Konzept Grenzen. Provokant gefragt:
+
+* Freitags hat Dein Verein Schwimmtraining. Dein Traingsplan nicht.  
+  **Wechselst Du den Verein?**
+* Dich interessiert Der Zweck einer Trainingseinheit.  
+  ***Wie gut erklärt Dir das Dein Trainingsplan?***
+* Du hast eine Frage.  
+  ***Welche Telefonnummer hat Dein Trainingsplan?***
+* Mittwochs wird es immer lang im Job. Im Trainingsplan steht ein long run.  
+  ***Kannst Du ihn einfach auf Dienstag legen?***
+* Du bist gelaufen. Es lief nicht so toll.  
+  ***Welches Feedback gibt Dir Dein Traingsplan?***
+* Dein Kind hat Geburtstag und Du möchtest Dein Training verschieben.  
+  **Wie geht Dein Trainingsplan damit um?**
+* Mist! Du hast Dich erkältet.  
+  **Ist das in Deinem Trainingsplan vorgesehen?**
+* Du bist tierisch gut drauf, denn Du schwimmst wie ein Fisch und läufst wie eine Schildkröte.  
+  **Weiß Dein Trainingsplan das?**
+* Du hast Dich verletzt.  
+  **Kennt Dein Trainingsplan eigentlich einen guten Physio?**
+* Du planst ein Trainingslager.  
+  **Dein Plan auch?**
+* Sunday-Group-Ride.  
+  Geplant: Kurz, flach, locker.  
+  Gemacht: 8000Watt, 130km, 1800Hm, 5 Ortschilder gewonnen und 3 Segmente geholt.  
+  **Wie spontan baut Dein Trainingsplan einen Ruhetag ein?**
+* Endlich Race-Day!  
+  *Dein Trainingsplan entwirft den Matchplan, steht am Streckenrand und feuert Dich an. Tut er nicht?*
+
+Ein Coach kann noch etwas ganz anderes:  
+Loben und Kritisieren.  
+Vertrauen und Zutrauen.
+Er hat das Coaches-Eye - das hat selbst eine KI nicht.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warum-einen-coach'), (SELECT id FROM categories WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warum-einen-coach'), (SELECT id FROM tags WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warum-einen-coach'), (SELECT id FROM tags WHERE slug='saisonplanung'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warum-einen-coach'), (SELECT id FROM tags WHERE slug='psyche'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warum-einen-coach'), (SELECT id FROM tags WHERE slug='training'));
diff --git a/db/articles/016_blog_gesundheit.sql b/db/articles/016_blog_gesundheit.sql
new file mode 100644 (file)
index 0000000..7a40da1
--- /dev/null
@@ -0,0 +1,14 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/gesundheit', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/gesundheit'), 1, (SELECT id FROM :"schema".categories WHERE slug='coaching'), 'Gesundheit!', NULL, NULL, 'Der Körper ist das Kapital. Gesundheit steht an allererster Stelle – vor jeder Trainingseinheit.', '## Gesundheit ist A und O
+
+Grundsätzlich empfehle ich eine ärztliche Untersuchung vor der Aufnahme des Trainings; am besten eine offizielle Bescheinigung auf Deine Sporttauglichkeit.
+
+Selbst bei Profis gilt: Der Körper ist das Kapital und die Gesundheit steht an allererster Stelle. Das ist bei aller Lust, auch mal an die eigenen Grenzen zu gehen, die Präambel allen sportlichen Tuns.
+
+Und [während des Trainings](https://www.triathlon-coaching.com/blog/wenn-du-krank-bist) gilt das erst recht.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/gesundheit'), (SELECT id FROM categories WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/gesundheit'), (SELECT id FROM tags WHERE slug='gesundheit'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/gesundheit'), (SELECT id FROM tags WHERE slug='coaching'));
diff --git a/db/articles/017_blog_mittwochs-faengt-die-woche-an.sql b/db/articles/017_blog_mittwochs-faengt-die-woche-an.sql
new file mode 100644 (file)
index 0000000..0ca887b
--- /dev/null
@@ -0,0 +1,14 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/mittwochs-faengt-die-woche-an', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/mittwochs-faengt-die-woche-an'), 1, (SELECT id FROM :"schema".categories WHERE slug='coaching'), 'Mittwochs fängt die Woche an', NULL, NULL, 'Warum ich nicht nach Kalenderwochen plane – sondern von Mittwoch bis Dienstag.', '## Warum Mittwochs?
+
+Es ist ziemlich üblich, sich an die Kalenderwochen zu halten, was auch auf der Hand liegt.
+
+Davon weiche ich ab. Warum?  
+Spätestens am Mittwoch hat man das Wochenende verkraftet, ob Samstag oder Sonntag ein (Trainings-)Wettkampf war oder nicht.
+
+Und deshalb hat es sich als praktisch und sinnvoll erwiesen immer von Mittwoch bis Dienstag zu planen.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mittwochs-faengt-die-woche-an'), (SELECT id FROM categories WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mittwochs-faengt-die-woche-an'), (SELECT id FROM tags WHERE slug='coaching'));
diff --git a/db/articles/018_blog_mein-coaching-ansatz.sql b/db/articles/018_blog_mein-coaching-ansatz.sql
new file mode 100644 (file)
index 0000000..228b852
--- /dev/null
@@ -0,0 +1,26 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/mein-coaching-ansatz', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/mein-coaching-ansatz'), 1, (SELECT id FROM :"schema".categories WHERE slug='coaching'), 'Mein Coaching-Ansatz', NULL, NULL, 'Maßgeschneidert statt von der Stange', '## Maßgeschneidert statt von der Stange
+
+Das Internet, KI-Assistenten und die einschlägigen Zeitschriften sowie Bücher sind voll mit Trainingsplänen. Und schlecht oder gar falsch sind diese auch nicht. Und wenn man danach trainiert, wird man sich irgendwie auch verbessern.
+
+Aber ist dieser für Dich optimal? Passt er zu Deinen Stärken und Schwächen? Werden Deine Defizite aufgearbeitet?
+
+Ein Trainingsplan aus der Literatur geht immer von Bedingungen aus, die in der Realität nicht vorkommen. Geschäftstermine, Familienfeiern, Öffnungszeiten von Schwimmbädern, Urlaube, die keine Trainingslager sind – auf all das nimmt ein Trainingsplan aus der Zeitschrift keinerlei Rücksicht.  
+Aber ich kann das einplanen und Dich beraten.
+
+Individuelles Training kann sich auf genau diese Rahmenbedingungen einstellen. So muss kein Training einfach ausfallen, was für Dich auch frustrierend ist, da Du damit auch um sein Ziel fürchtet. Der Plan richtet sich nach Dir und Deinen Freiräumen.
+
+Ein Trainingsplan ist wie ein Anzug. Es gibt welche von der Stange, die irgendwie schon passen, oder es gibt Maßanzüge.
+
+## Fragen und Feedback
+
+Ein Buch kannst Du nicht Fragen – Deinen Coach sehr wohl. Warum soll ich diese Einheit machen? Ist die wichtig? Wie ist diese Einheit gemeint? Kann ich Die Mittwochseinheit vorziehen? Selbstverständlich kann man sich das Wissen aneignen und die Fragen selber beantworten.  
+Oder man hat jemand, der sich damit auskennt und man kann sich auf das Wesentliche konzentrieren: Arbeiten, Trainieren, Essen, Schlafen 😉', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mein-coaching-ansatz'), (SELECT id FROM categories WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mein-coaching-ansatz'), (SELECT id FROM tags WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mein-coaching-ansatz'), (SELECT id FROM tags WHERE slug='training'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mein-coaching-ansatz'), (SELECT id FROM tags WHERE slug='triathlon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/mein-coaching-ansatz'), (SELECT id FROM tags WHERE slug='lifestyle'));
diff --git a/db/articles/019_blog_grenzen-wofur-ich-nicht-da-bin.sql b/db/articles/019_blog_grenzen-wofur-ich-nicht-da-bin.sql
new file mode 100644 (file)
index 0000000..bbe16da
--- /dev/null
@@ -0,0 +1,31 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/grenzen-wofur-ich-nicht-da-bin', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/grenzen-wofur-ich-nicht-da-bin'), 1, (SELECT id FROM :"schema".categories WHERE slug='coaching'), 'Grenzen: Wofür ich nicht da bin', NULL, NULL, 'Als Dein Coach bin ich weder Dein Drill-Sergeant, noch Dein 6-a.m.-Double-Espresso-Barista', '## Deine Motivation
+
+Eine Athletin hat mir mal abgesagt, weil sie "keinen Tritt in Ihren Allerwertesten bräuchte".  
+Zugegebenermaßen war ich schockiert.
+
+Denn ein Coaching hat keinen Anspruch, grundsätzliche Motivationsquelle zu sein.
+Das ist nicht mein Job.
+
+Für Deine Motivation bist Du zuständig.
+
+Als Dein Coach bin ich weder Dein Drill-Sergeant, noch Dein 6-a.m.-Double-Espresso-Barista.
+
+Trotzdem kann es sein, dass Du Dich dem Trainer unter Umständen mehr verpflichtet fühlst als Dir selbst.  
+Du hast im Hinterkopf, dass der Trainer nachfragt, warum diese eine Einheit anders durchgeführt wurde oder gar ganz ausgefallen ist.
+
+Und ja, wenn Du mal durchhängst, bin ich auch für Dich da.
+
+Allerdings: **DU** musst wollen.
+
+**Dein Wille** 
+**Deine Ziele** 
+**Deine Visionen**
+
+... ich helfe Dir nur auf dem Weg dahin.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/grenzen-wofur-ich-nicht-da-bin'), (SELECT id FROM categories WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/grenzen-wofur-ich-nicht-da-bin'), (SELECT id FROM tags WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/grenzen-wofur-ich-nicht-da-bin'), (SELECT id FROM tags WHERE slug='motivation'));
diff --git a/db/articles/020_blog_ziele-setzen-aber-richtig.sql b/db/articles/020_blog_ziele-setzen-aber-richtig.sql
new file mode 100644 (file)
index 0000000..6da7ecb
--- /dev/null
@@ -0,0 +1,67 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/ziele-setzen-aber-richtig', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), 1, (SELECT id FROM :"schema".categories WHERE slug='blog'), 'Ziele setzen – aber richtig!', NULL, NULL, 'SMART-Ziele für Triathleten: spezifisch, messbar, attraktiv, realistisch und terminiert.', '## Aloha!
+
+Für den Einen oder Anderen ist die Saison noch nicht zu Ende, ein später Marathon oder gar der Ironman Hawaii stehen noch auf dem Programm. Die meisten von Euch befinden sich in der Off-Season und machen sich Gedanken um die nächste Saison. Die Gedankenfetzen kreisen um „Ich würde ja gerne …“, „Lust hätte ich auf…“ oder sind schon einen Schritt weiter und ganz konkret „Ich bin gemeldet in … am“.
+
+Selbst die, die schon wissen, WO sie starten, wissen noch nicht unbedingt, WAS sie da erreichen wollen. Klar, das Ziel, also finishen. Ein DNF plant wahrscheinlich niemand. 😉
+
+### Letztendlich geht es darum, wie man sich welches Ziel setzt.
+
+Dabei geht es um folgende Fragen:
+
+* Gibt es einen Termin und Ort?
+* Was bin ich bereit zu investieren?
+* Wie sind meine Voraussetzungen?
+* Was ist meine Vision?
+* Welche Steigerungen traue ich mir zu bzw. sind nicht völlig utopisch.
+
+Termin und Ort – das ist am einfachsten zu klären. Diejenigen, die sich beispielsweise in Roth um 6 Uhr morgens in die Schlange stellen, um einen Startplatz zu ergattern, zeigen mit dem Finger schräg gegenüber auf den Festplatz mit dem Zielbogen und sagen: „Ich will da durchlaufen. Am …“ Und der Termin ist für sie präsenter als der eigene Geburtstag. Termin und Ort sind also in Stein gemeißelt. Für diejenigen, die im Herbst noch zwischen Wünschen und Ideen die richtige Inspiration suchen, kristallisiert sich irgendwann auch etwas konkretes, sprich ein Ort und ein Datum, heraus.
+
+Aber wenn man dann weiter fragt – „In welcher Zeit?“, geht das Gedruchse los. Die Antworten reichen von „Schaun mer mal“ über „Nur Finishen“ bis hin zu „Dem Blumi einen einschenken“. Der Leser mag schmunzeln, wenn er sich da vielleicht wiedererkennt.
+
+In den Köpfen diskutieren dann Engelchen und Teufelchen: „Sub 10 geht bestimmt.“ – „Mehr als 10 Stunden Training schaff ich nicht.“ – „Und im Januar fange ich einen neuen Job an.“ – „Ja, aber da sparst Du 1 Stunde Arbeitsweg pro Tag.“ – „Von 11:45 nach 10 ist zu viel auf einmal, ich Bleiente pack den Marathon nie unter 4, wie soll das gehen?“ – „Aber wenn Hawaii kein Traum bleiben soll ….“ – „Hey, werde mal nicht größenwahnsinnig, in der AK70 vielleicht, da brauchst keine Quali.“ – „Ich bin erst 25!“
+
+Die Abwägungen im Kopf sind vielfältig und so amüsant sich dieser Dialog hoffentlich liest, stecken da viele Aspekte einer richtigen, korrekten Zielsetzung drin.
+
+Die sollte eben „SMART“ sein. SMART steht dabei für die Anfangsbuchstaben von **„spezifisch“, „messbar“, „attraktiv“, „realistisch“ und „terminiert“** und definieren die Eigenschaften einer guten Zielsetzung.
+
+Jetzt atmen wir einmal durch und gucken uns das genauer an.
+
+### spezifisch, ...
+
+Was ist denn „spezifisch“? Ein spezifisches Ziel ist eines, das **konkret präzisiert** wird. Also ziemlich genau das Gegenteil von „Schaun mer mal“. Hosen runter lassen ist angesagt. Zum Beispiel: „Ich will endlich den Marathon unter 4 Stunden laufen. „Das ist so einfach wie das Schreiben des Wunschzettels zu Weihnachten. Mach eine ganz konkrete Ansage! Keine Hemmungen, nicht zögern, sondern Zack und raus damit. Und am besten gleich aufschreiben. Ob man das gleich der ganzen Welt wissen lässt oder vielleicht nur dem Partner, bleibt jedem selbst überlassen.
+
+### ... messbar, ...
+
+Mit dem Ziel, den Marathon unter 4 Stunden zu laufen, ist sogleich ein **messbares Ziel** gesetzt. Die Uhren sind unbestechlich und somit gibt es für das Ziel die beiden Zustände „erreicht“ und „nicht erreicht“. Schwieriger sind Ziele, die von Einflussfaktoren abhängen, die außerhalb der eigenen Macht stehen. Platzierungen zu erreichen hört sich ganz konkret mess- und überprüfbar an, aber ob die Konkurrenz mitspielt, weiß man nicht. Die Leichtathletik-Ikone der 80er-Jahre, Harald Schmidt, wollte bestimmt Olympiasieger und Weltmeister über die 400m Hürden werden, leider war Edwin Moses immer schneller. Eine persönliche Bestzeit ist sicher keine schlechte Leistung, aber für das Ziel, den Titel, reichte es nicht. An diesem Beispiel wird deutlich, dass **Platzierungen ein Wunsch sein dürfen, aber kein Ziel sein sollten**.
+
+### ... attraktiv, ...
+
+„Nur Finishen“ ist übrigens auch ein messbares, nämlich ein Zeit-Ziel, denn es gibt den Zielschluss. Aber außer einem Newbie und Wenigtrainierer kauft keiner ein derart formuliertes Ziel ab. Warum? Jeder vermutet, dass da einer nicht die Wahrheit über seine eigentliche Zielsetzung erzählt, da die Herausforderung fehlt. Das Ziel erscheint einfach nicht **attraktiv**. Ein Finish ist unbestritten eine respektable Leistung, bitte nicht missverstehen, und schlicht die Mindestvoraussetzung für Weiteres, aber wenn der 1:10-Halbmarathoni beim Marathon sich nur die Finisher-Medaille abholen will, ist das einfach nicht glaubwürdig. Schon alleine deshalb, weil er sich ja um sein Anfangstempo Gedanken machen wird, welches er sich zutraut, es durchzuhalten. Ein **attraktives Ziel muss ein Kitzel sein, eine Challenge** und nichts, was man im Vorbeigehen erledigt. 2:30 wäre ein Beispiel für unseren Halbmarathoni. Das ist machbar, fällt ihm aber nicht in den Schoß.
+
+### ... realistisch, ...
+
+Und es ist realistisch. 2:21 ist bei dieser Zeit auf der Unterdistanz nicht möglich. Oder: Wenn der 9:00-local-hero vom Triathlonverein „den Frodo versenken“ will, wird er bestenfalls ausgelacht. Der sieht den Frodo höchstens in der Wechselzone – und zwar beim Rad-Check-In. Dieses Ziel nehmen wir weltweit höchstens einer Handvoll Athleten ab. Etwas Anderes ist es, wenn unser schon arg strapazierte Halbmarathoni 22 ist und die 2:20 in 3 Jahren knacken möchte. Das kann realistisch sein, vorausgesetzt, er schafft das Training und bleibt gesund. Er ist noch jung genug und noch steigerungsfähig und in 3 Jahren kann man eine Menge erreichen. Die **Lebensumstände und das Alter** sind auch ein Aspekt, der darüber entscheidet, ob ein Ziel realistisch ist. Die Vollzeit arbeitende und alleinerziehende Mutter von 3 Kindern, die Ambitionen auf eine baldige Hawaii-Quali hat, ist entweder gnadenlos talentiert, perfekt organisiert und die Kinder sind absolut problemlos oder sie ist auf dem besten Weg in die Frustration.
+
+### ... und terminiert !
+
+„Terminiert“ ist der letzte Punkt der Zielerreichung. **Sobald ein Wettkampf im Spiel ist, steht auch ein Datum im Kalender**. Und dann kann es losgehen mit der Zielsetzung. Zum Beispiel: „Ich möchte 2020 beim Ostseeman unter 11 Stunden finishen.“ „Meine aktuelle Bestleistung ist bei 12 Stunden, ich habe einen 9-to-5-Job und bin gesund.“ Man kann jetzt noch über die Attraktivität des Ziels streiten, aber als Demonstration sollte das an dieser Stelle genügen.
+
+Das Setzen SMARTer Ziele geht auch **über den Sport hinaus**. „Ich möchte bis Weihnachten 10 Kilo abnehmen“. „Ich möchte zum Jahresende XY 1000 Euro ansparen.“. Beispiele für SMARTe Ziele finden sich überall.
+
+### Was heißt das konkret in der Praxis?
+
+Ziele aufschreiben und mit ein paar Vertrauten, dem Trainer, dem Partner **kritisch diskutieren und hinterfragen**. Als sinnvoll haben sich auch **Zwischenziele** erwiesen, denn die #roadtokona ist lang. Zwischenziele stellen auf dem Weg zur Vision eine hilfreiche **Erfolgs- und Fortschrittskontrolle** dar. Wer will denn schon vom Weg abkommen?
+
+Auch für die Motivation ist es förderlich und eigentlich unabdingbar, sich von **Zwischenziel zu Zwischenziel dem Traum anzunähern**. Denn sollte der Traum ein Traum bleiben, kann man sich dennoch über jede Menge anderer Erfolge freuen. [Harald Schmid](https://de.wikipedia.org/wiki/Harald_Schmid_(Leichtathlet)) (400m Hürden) ist bestimmt immer noch stolz wie Oskar über 5 mal EM-Gold und 13 nationale Titel – und völlig zu recht! Auch wenn Edwin Moses ihm die wichtigen Titel weggeschnappt hat.
+
+**Die Vision ist das Gipfelkreuz**, auf dem Weg dahin sind viele Schritte zu gehen.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), (SELECT id FROM categories WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), (SELECT id FROM tags WHERE slug='saisonplanung'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), (SELECT id FROM tags WHERE slug='training'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), (SELECT id FROM tags WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), (SELECT id FROM tags WHERE slug='mindset'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/ziele-setzen-aber-richtig'), (SELECT id FROM tags WHERE slug='motivation'));
diff --git a/db/articles/021_blog_wenn-du-krank-bist.sql b/db/articles/021_blog_wenn-du-krank-bist.sql
new file mode 100644 (file)
index 0000000..2deaa6b
--- /dev/null
@@ -0,0 +1,23 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/wenn-du-krank-bist', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/wenn-du-krank-bist'), 1, (SELECT id FROM :"schema".categories WHERE slug='angebot'), '... wenn Du krank bist ...', NULL, NULL, 'Mit Symptomen einer Erkrankung gilt: Trainingsverbot! Krankheitszeiten sind bei mir kostenfrei.', '## ... bist Du krank!
+
+Mit Wehwehchen oder Symtomen einer (Atemwegs-)Erkrankung gilt: **Trainingverbot!**
+
+Natürlich kann man mit einer Schürfwunde meistens ein Lauftraining machen. In diesem Fall baue ich das Training um und die Schwimmsachen bleiben trocken.
+
+Aber es ist Keinem gedient – weder Dir noch mir – wenn man sich mit irgendwelchen Verletzungen oder Krankheiten durch die Saison schleppt und deswegen nicht den erwünschen Erfolg hat. Von langfristigen Schäden und chronisch werdenden Dingen ganz zu schweigen.
+
+Lebensgefährlich wird es, wenn sich bakterielle Infektionen aufs Herz setzen.
+
+Aus diesem Grund sind **Krankheitszeiten** bei mir **kostenfrei**.
+
+Ich möchte nicht, dass Du den Gedanken entwickelst, durch das Gefühl „für nichts“ zu bezahlen, zu früh wieder anfängst oder gar durchtrainierst. Zum gesund werden brauchst Du die Zeit, die Du dafür brauchst, aber auf keinen Fall Druck.
+
+[Gesundheit](https://www.triathlon-coaching.com/blog/gesundheit) ist unbezahlbar.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/zwenn-du-krank-bist'), (SELECT id FROM categories WHERE slug='angebot'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/wenn-du-krank-bist'), (SELECT id FROM tags WHERE slug='coaching'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/wenn-du-krank-bist'), (SELECT id FROM tags WHERE slug='gesundheit'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/wenn-du-krank-bist'), (SELECT id FROM tags WHERE slug='mindset'));
diff --git a/db/articles/022_blog_was-nicht-auf-strava-ist-ist-nicht-passiert.sql b/db/articles/022_blog_was-nicht-auf-strava-ist-ist-nicht-passiert.sql
new file mode 100644 (file)
index 0000000..0af6163
--- /dev/null
@@ -0,0 +1,25 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/was-nicht-auf-strava-ist-ist-nicht-passiert', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), 1, (SELECT id FROM :"schema".categories WHERE slug='blog'), 'Was nicht auf Strava ist, ist nicht passiert?', NULL, NULL, 'Warum ich nicht bei Strava bin – und warum Fokus wichtiger ist als Kudos.', '## Warum ich nicht bei Strava bin.
+
+Weil ich öfter gefragt werde...
+
+- Es geht Keinen was an, wann, wo, wie, was und wieviel ich trainiere.
+- Mir reichen die Daten auf Garmin & TrainingPeaks vollkommen aus.
+- Mit Instagram bin ich in Sachen Socialmedia vollkommen ausgelastet. Ich brauche kein weiteres Tools, um Likes, Herzchen, Kudos oder sonstwas zu verteilen oder zu bekommen.
+- Strecken .... Wenn ich noch erzähle, dass ich auch keinen Komoot-Account habe, hältst Du mich für einen Tech-Verweigerer. Ich muss Dich enttäuschen, ich bin als IT-ler digital genug.
+- Es gibt zu viele Rad-Segmente, die sind einfach nur krank. Entweder ist das notwendige Risiko nach meiner Ansicht nicht zu verantworten oder es ist eine Fahrweise notwendig, die nicht zur Deeskalation im Straßenverkehr beiträgt. Oder beides. Das möchte ich nicht unterstützen.
+
+Soweit so gut.
+
+**Das Wichtigste ist jedoch:**  
+Voller Fokus auf die Trainingseinheit statt Posing und Siege statt Segmente ;-)
+', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), (SELECT id FROM categories WHERE slug='blog'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), (SELECT id FROM tags WHERE slug='bike'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), (SELECT id FROM tags WHERE slug='triathlon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), (SELECT id FROM tags WHERE slug='lifestyle'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), (SELECT id FROM tags WHERE slug='szene'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/was-nicht-auf-strava-ist-ist-nicht-passiert'), (SELECT id FROM tags WHERE slug='training'));
diff --git a/db/articles/023_blog_laufschuhe-kann-man-zu-viele-haben.sql b/db/articles/023_blog_laufschuhe-kann-man-zu-viele-haben.sql
new file mode 100644 (file)
index 0000000..d75554b
--- /dev/null
@@ -0,0 +1,72 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/laufschuhe-kann-man-zu-viele-haben', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), 1, (SELECT id FROM :"schema".categories WHERE slug='blog'), 'Laufschuhe – Kann man zu viele haben?', NULL, NULL, 'Best practices rund um Laufschuhe: Anzahl, Marken, Tempi und Wettkämpfe.', '## Laufschuhe
+
+Laufschuhe sind die mit Abstand wichtigsten Ausrüstungsgegenstände beim Laufen.  
+Sie sollen den Fuß schützen und führen. Sie sollen die Laufbewegung unterstützen und die Gelenke schonen. Ganz schön viele Aufgaben für ein paar Hundert Gramm Plastik.
+
+Und es gibt für verschiedene Aufgaben Spezialisierungen - von Spikes bis zum Trail.
+
+## Best practices:
+
+### Je mehr Du läufst, je mehr Schuhe solltest Du besitzen.
+
+**Faustregel:** Minimum 3 und pro Lauftag in der Woche 1 Paar. Wenn 5 Mal pro Woche läufst, hast Du 5 Paar Schuhe; Spikes, "reine" Wettkampfschuhe ausgenommen.
+
+### Trenne Dich von alten Schätzchen.
+
+Persönliche Anmerkung: Ich kenne jemanden, der mir diesen Satz um die Ohren haut.  
+Im Ernst: Ist das Ding durchgelaufen - dann in die Tonne damit.
+
+### Mische die Marken.
+
+Laufschuhmarken haben alle ihre Eigenarten im Leisten oder im Aufbau der Sohlen. Die Hersteller machen sich allerhand Gedanken, wie sie den Schuh bauen und wenden ihre Erkenntnisse gerne auf mehrere Modelle an. Das ist ökonomisch sinnvoll, führt aber dazu, dass die Marken einen eigenen Charakter entwickeln, der sich nur langsam über mehrere Produktzyklen hinweg ändert.  
+Wenn Du zu ähnliche Schuhe hast oder ein Marken-Fan bist, kann es zu Fehlstellungen führen. Manchmal verschwindet auch so manches Zipperlein, wenn Du den Schuh wechselst.
+
+### Habe für verschiedene Lauftempi auch verschiedene Schuhe.
+
+Du hast verschiedene Lauftempi: Langsam, mittel, schnell, sehr schnell - das macht 1 Schuh zum "Rumschlappen", 1 für mittel bis langsame Läufe, 1 für mittel bis schnelle Läufe, 1 für schnell bis All-out. Wenn Du auf der Bahn trainierst, empfiehlt sich einer, der auch auf einer nassen Bahn gut haftet, sofern man keine Spikes tragen möchte.
+
+### Habe für verschiedene Wettkämpfe auch verschiedene Schuhe.
+
+Ein schneller 10km auf der Straße braucht einen leichten, schnellen Schlappen ohne großes Profil und Dämpfung ist weniger relevant.  
+Ein 100km Lauf im Gelände stellt das andere Extrem dar. Ordentliches Profil, Dämpfung und Führung für einen müden Bewegungsapparat sind in diesem Fall wichtiger als Gewicht.
+
+### Unterschiede zwischen Wettkampf- und Trainingsschuh gibt es nicht wirklich.
+
+Dem Schuh ist es egal, ob Du eine Startnummer trägst oder nicht.  
+Und Du solltest einen Schuh niemals das erste Mal im Wettkampf laufen.  
+Dennoch entsteht im Läuferleben dann doch das eine oder andere Paar, dass dann doch nur im Wettkampf gelaufen wird. Das ist einfach auch Kopfsache.
+
+### Berücksichtige Dein Lauftempo.
+
+Ein ehrlicher Blick in den Spiegel bitte: Wenn 55 Minuten auf 10km für Dich schnell sind, ist das Tempo nicht schnell. Dann reichen die Trainingslaufschuhe auch für den Wettkampf, da sich Dein Wettkampf-Laufstil vom Training nicht groß unterscheidet. Schnrittlänge, Kniehub, Schrittfrequenz - all das ist eben Dauerlauf.
+
+### Für Triathlon gibt es keine Sonderregeln. Eigentlich.
+
+Im Triathlon-Wettkampf ist das Lauftempo auf gleicher Strecke geringer. Sprich 10km auf der Straße sind langsamer als 10km bei einer olympischen Distanz.  
+Ein schneller Einstieg mit Gummischnürbändern sollte möglich ist, wie relevant das bei einem 4-Stunden-Marathon ist, kann sich jeder selber überlegen. In einem Ligarennen ist das sicher relevant.
+
+### Und .... Spikes?
+
+Man unterscheidet zwischen Bahn- und Crossspikes. Kann man haben, muß man aber nicht. Muss man haben, wenn man ernsthaft Bahnläufe macht.
+
+### Kaufe im Fachgeschäft.
+
+Natürlich kann man sich im Versandhandel 10 Paar Schuhe kaufen und 9 zurückschicken. Die Sinnhaftigkeit dessen ist eine Sache, die andere Sache ist die:  
+Guckt der Versender zu, wenn Du den Schuh auf dem Laufband testet?
+
+### Im Trainingslager:
+
+2 Paar mitnehmen. 1 Paar ist zu wenig.
+', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM categories WHERE slug='blog'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='running'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='triathlon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='training'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='raceday'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='duathlon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='marathon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/laufschuhe-kann-man-zu-viele-haben'), (SELECT id FROM tags WHERE slug='equipment'));
diff --git a/db/articles/024_blog_bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn.sql b/db/articles/024_blog_bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn.sql
new file mode 100644 (file)
index 0000000..d839283
--- /dev/null
@@ -0,0 +1,64 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), 1, (SELECT id FROM :"schema".categories WHERE slug='blog'), 'Bahn-Knigge: Die ungeschriebenen Gesetze auf der Bahn', NULL, NULL, 'Triathleten sind Gäste auf der Leichtathletikanlage. Diese Regeln solltest du kennen.', '## Leichtathletik ist eine eigene Welt
+
+Auch wenn beim Triathlon Laufen dabei ist, sind Triathleten keine Läufer.  
+Das fängt damit an, dass lächerliche 😉 3000m schon eine Langstrecke sind und ein Sprinttriathlon im besten Fall weniger als eine Stunde dauert.
+
+In der Leichtathletik gibt es natürlich noch Sprung, Stoß und Wurf, aber das nur der Vollständigkeit halber.  
+Alles andere ist irgendwie Laufen und findet auf der Bahn statt.
+
+Die Innenbahn einer Leichtathletikanlage ist exat 400 m lang, gemessen in 30 cm Abstand zur Innenkante. Und auf der finden unsere Tempoläufe statt, aber auch die der Leichtathletik-Abteilung.  
+Wenn Du nicht gerade zu den Allerschnellsten im Triathlon gehörst, zeigt Dir ein Bahnläufer in der Regel die Hacken. 60 Sekunden / Runde ( 2:30er Schnitt) kommen vor und sind eine völlig andere Welt.
+
+Damit das sportlich fair und respektvoll sowie unfallfrei von statten geht gibt es diese ungeschriebenen
+
+## Regeln:
+
+### Fairness:
+
+Triathleten sind in der Regel zu Gast auf einer Leichtahletikanlage. Oft findet dort auch Nachwuchstraining statt – als erwachsener Sportler bist Du Vorbild.
+
+### Wir laufen IMMER gegen den Uhrzeigersinn.
+
+Wer das mal anders machen möchte: gerne, solange Du alleine bist. Sobald jemand dazustösst: Kehrt marsch!
+
+### Überholt wird rechts.
+
+Wie auf einer deutschen Autobahn: Rechts der Sportwagen, Links der LKW.  
+Und: Fahre solange links, bis im Rückspiegel was Schnelleres auftaucht, und wechsle dann eine Spur nach rechts.
+
+### Mache Platz.
+
+Wenn von hinten einer aufläuft, weichst Du nach links aus. Es reichen wenige Schritte auf Bahn 2, dann schlupft der Überholer durch.  
+Warum? Das geht schneller als, wenn der Schnellere den langen Weg außen herum machen muß.
+
+### Keine Kopfhörer.
+
+Man orientiert sich sehr viel duch Gehör. Du hörst, wenn von hintern der ICE anrauscht oder besser anschnauft.
+
+### Sein laut.
+
+Wenn Du überholen möchtest: Mache Dich bemerkbar. „Innen frei!“ reicht völlig aus. Wenn Du das nicht mehr kannst, hört man Dich auch so – siehe oben.
+
+### Trabpausen NIEMALS auf Bahn 1.
+
+Du kannst in den Innenraum auf den Rasen ausweichen, sofern der Platz frei ist und da keine Speere fliegen. Oder Du nimmst die Bahn 2 oder 3.  
+Hierbei bitte darauf achten, den (Hürden-)Sprintern nicht vor die Füße zu laufen.
+
+### NICHT Anhalten.
+
+Zumindest niemals auf der Innenbahn. Lieber ein paar Schritte auf Bahn 2 austrudeln.
+
+### Wenn Du mit den Läufern trainierst:
+
+Insbesondere Bahnläufer sind Körperkontakt gewohnt; im Wettkampf wird auch schon mal der Ellebogen eingesetzt oder in die Hacken getreten.  
+Das ist Triathleten in etwa so fremd, wie einem Beckenschwimmer, der beim Triathlon mitmacht und zum ersten Mal mit der Masse ins Wasser rennt.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), (SELECT id FROM categories WHERE slug='blog'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), (SELECT id FROM tags WHERE slug='running'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), (SELECT id FROM tags WHERE slug='training'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), (SELECT id FROM tags WHERE slug='marathon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), (SELECT id FROM tags WHERE slug='leichtathletik'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/bahn-knigge-die-ungeschriebenen-gesetze-auf-der-bahn'), (SELECT id FROM tags WHERE slug='fairplay'));
diff --git a/db/articles/025_blog_warm-up-vor-einem-laufwettkampf.sql b/db/articles/025_blog_warm-up-vor-einem-laufwettkampf.sql
new file mode 100644 (file)
index 0000000..f251c40
--- /dev/null
@@ -0,0 +1,49 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/warm-up-vor-einem-laufwettkampf', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), 1, (SELECT id FROM :"schema".categories WHERE slug='blog'), 'Warm-Up vor einem Laufwettkampf', NULL, NULL, 'Aufgewärmt heißt bereit zur unmittelbaren Leistungsabgabe. So geht das richtige Warm-Up.', '## Warm-Up
+
+Aufgewärmt heißt, Muskeln und Stoffwechsel sind bereit zur unmittelbaren und hohen Leistungsabgabe.  
+Sich warm fühlen ist was anderes. Das tue ich auch morgens, wenn ich aus dem Bett komme. Aber wir wissen, dass wir dann nicht lossprinten können. Außer zur Kaffeemaschine 😉
+
+Und so gehts:
+
+* Startnummer abholen und anbringen.  
+  Ich trage beim Einlaufen schon die Wettkampfkleidung unten drunter, dann ist das Offizelle schon erledigt.
+* 45-60 min vor dem Start:  
+  Einlaufen, erst ultra gemütlich, dann steigern auf „schneller als Ga1“.
+  Einen Riegel oder eine Banane essen.
+* Spätestens nach dem Einlaufen:  
+  Verdauung in Ordnung bringen. Je nachdem wie die Örtlichkeiten sind, solltest Du die (Warte-)Zeit dafür einplanen.
+* 25 min vor dem Start:  
+  Kurz dynamisch dehnen (Indoor, sofern kalt draußen und möglich)
+* 20 min vor dem Start:  
+  Lauf-ABC in leichte Steigerungen übergehen: Fußgelenkslauf, Skippings, Anfersen 1-2mal pro Übung.
+* 10 min vor dem Start:  
+  Traben, Gelenke durchbewegen, 1-2 lockere (!!!) Steigerungen.
+  Jetzt ist Zeit für das letzte Gel!
+* 5 min vor dem Start:  
+  Jacke / warme Oberbekleidung reinbringen / abgeben.  
+  Am Start leicht frieren ist okay!
+* 3 min vor dem Start:  
+  Ins Startfeld einreihen, rumtippeln, in Bewegung bleiben.
+* Start:  
+  Vollgas! 🔥🔥🔥🔥🔥
+
+Als Faustregel gilt:  
+Je kürzer die Strecke, je höher ist das Tempo und je wärmer muß ich sein. Bei 800m läuft der Körper schon auf Hochtouren, bei 100km reicht eine leichte Mobilisation.
+
+Falsch wäre (bspw, aber schon häufig so beobachtet) 10 min traben, 15 min Schlange stehen vor dem Dixi, 20min Smalltalk mit 75 verschiedenen Menschen im Gebäude, rausgehen, feststellen, dass es kalt ist, noch ne Jacke/Mütze/Hose extra anziehen, loslaufen, nach 4 km tatsächlich warm sein, um den Preis viele Körner verschossen zu haben und dann merken, dass der Kreislauf durchdreht, weil die Thermoregulation abgedreht wurde durch zu viele Klamotten.
+
+## Im Ziel
+
+Anziehen, auslaufen und verpflegen, Stretching und nach Hause fahren.  
+Oder wenn es zu ungemütlich ist, zu Hause 30min locker auf der Rolle ausfahren und dann Stretching, Essen , Dehnen, Kuchen essen.', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), (SELECT id FROM categories WHERE slug='blog'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), (SELECT id FROM tags WHERE slug='raceday'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), (SELECT id FROM tags WHERE slug='running'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), (SELECT id FROM tags WHERE slug='taktik'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), (SELECT id FROM tags WHERE slug='marathon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/warm-up-vor-einem-laufwettkampf'), (SELECT id FROM tags WHERE slug='leichtathletik'));
+
diff --git a/db/articles/026_blog_saisonplanung-wie-geht-man-vor.sql b/db/articles/026_blog_saisonplanung-wie-geht-man-vor.sql
new file mode 100644 (file)
index 0000000..45690dd
--- /dev/null
@@ -0,0 +1,39 @@
+
+SET search_path TO :"schema"
+
+INSERT INTO :"schema".pages        VALUES (DEFAULT,                                                  'blog/saisonplanung-wie-geht-man-vor', (SELECT id FROM :"schema".pages WHERE slug='blog'), 'article', 0, true, NULL, NULL, now(), now());
+INSERT INTO :"schema".page_content VALUES (DEFAULT,       (SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), 1, (SELECT id FROM :"schema".categories WHERE slug='blog'), 'Saisonplanung – wie geht man vor?', NULL, NULL, 'Wie plane ich meine Saison? Vom Ziel zurück in die Gegenwart – in mehrwöchigen Zyklen.', '## Das Ziel bestimmt den Weg
+
+Thema eines anderen Blogs war die richtige [Zieldefinition](https://www.triathlon-coaching.com/blog/ziele-setzen-aber-richtig/). Was ist ein gutes Ziel und wie setze ich mir ein gutes Ziel. Und irgendwann ist es dann da, das Ziel. Und nun? Jetzt stehen wir da wie der sprichwörtliche Ochs vorm Berg und fragen uns: „Wie komme ich da hin?" Wie schaffe ich beispielsweise den Marathon in 3:30, also einen Schnitt von 5 min/km?
+
+Bergsteiger und Kletterer planen ihre Routen genau und wissen, welche Spalte und Vorsprünge der Eigernordwand begehbar sind, welche Seile und Ausrüstung sie brauchen und wie sie sich ernähren.
+
+Ein Ausdauersportler geht im Prinzip auch nicht anders vor. Dabei gibt es zwei Aspekte: Die zeitliche und die inhaltliche Ausprägung des Ziels.
+
+## Fokus beibehalten
+
+Ein Jahreshighlight in den Kalender einzutragen, ist die leichteste Übung. Und dann?
+
+Während der Bergsteiger vom Tal zum Berg plant, geht unser Marathoni den umgekehrten Weg und plant von seinem Marathon zurück Richtung Gegenwart. Und zwar in mehrwöchigen Zyklen. Die Entlastungswochen und Testwettkämpfe werden zu diesem Zeitpunkt bestimmt.
+
+Ich gehe sogar soweit, dass ich potentielle Testwettkampftermine festlege und dann schaue, wie das Veranstaltungsangebot zu diesen Daten ist. So suche ich zum Datum das Rennen anstelle zu überlegen, wie ich meine Lieblingsrennen, Traditionsveranstaltungen oder sonstige vom Umfeld mit Erwartungen überladenen Termine in die Periodisierung zu zwängen.
+
+Man darf schon die Wertigkeit des „38. Volkslauf um Meiers Kartoffelacker" des Heimatvereins im Vergleich zum Marathon in Bestzeit kritisch hinterfragen. Die Konsequenzen des Nein-Sagens muss man allerdings aushalten können und wollen. Das darf jeder mit sich selbst ausmachen.
+
+## Das Ziel muss passen
+
+Der inhaltliche Aspekt ist anders. Aus dem Ziel und der aktuellen Form folgt ein Soll und Ist, unser 3:50-Marathoni muss sich im Klaren sein, dass er auch seine 10 km Zeit auf ca. 45 Minuten verbessern muss, will er denn den Marathon in 3:30 laufen. Über die gesamte Saison hinweg entwickeln sich nicht nur die Leistungen auf den anderen Strecken mit, sondern auch die Trainingstempi passen sich an bzw. werden angepasst. Testwettkämpfe helfen dabei den Fortschritt sichtbar und messbar zu machen. Abgesehen davon: Ist eine notwendige Steigerung unrealistisch, dann passt das Ziel nicht und muss korrigiert werden.
+
+Saisonplanung ist vor allem auch eine ehrliche Auseinandersetzung mit sich selbst:
+
+- „Was kann ich?"
+- „Was will ich?"
+- „Was bin ich bereit zu tun?"', '', NULL, NULL, NULL, NULL, NULL, 'published', NULL, NULL, now(), now());
+INSERT INTO :"schema".content_pages VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM categories WHERE slug='blog'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='saisonplanung'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='running'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='triathlon'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='motivation'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='training'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='camp'));
+INSERT INTO :"schema".content_tags  VALUES ((SELECT id FROM :"schema".pages WHERE slug='blog/saisonplanung-wie-geht-man-vor'), (SELECT id FROM tags WHERE slug='mindset'));
diff --git a/db/dump-laktatnebel-202603181341_schema.sql b/db/dump-laktatnebel-202603181341_schema.sql
new file mode 100644 (file)
index 0000000..b92a858
--- /dev/null
@@ -0,0 +1,1158 @@
+--
+-- PostgreSQL database dump
+--
+
+-- Dumped from database version 16.4 (Debian 16.4-1)
+-- Dumped by pg_dump version 16.4 (Debian 16.4-3+b1)
+
+-- Started on 2026-03-18 13:41:21 CET
+
+SET statement_timeout = 0;
+SET lock_timeout = 0;
+SET idle_in_transaction_session_timeout = 0;
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = on;
+SELECT pg_catalog.set_config('search_path', '', false);
+SET check_function_bodies = false;
+SET xmloption = content;
+SET client_min_messages = warning;
+SET row_security = off;
+
+--
+-- TOC entry 6 (class 2615 OID 42159)
+-- Name: :"schema"; Type: SCHEMA; Schema: -; Owner: oleb
+--
+
+CREATE SCHEMA IF NOT EXISTS :"schema";
+SET search_path TO :"schema";
+
+
+ALTER SCHEMA :"schema" OWNER TO oleb;
+
+--
+-- TOC entry 882 (class 1247 OID 42198)
+-- Name: build_status_enum; Type: TYPE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TYPE :"schema".build_status_enum AS ENUM (
+    'running',
+    'success',
+    'partial',
+    'error'
+);
+
+
+ALTER TYPE :"schema".build_status_enum OWNER TO oleb;
+
+--
+-- TOC entry 879 (class 1247 OID 42188)
+-- Name: content_status_enum; Type: TYPE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TYPE :"schema".content_status_enum AS ENUM (
+    'draft',
+    'scheduled',
+    'published',
+    'archived'
+);
+
+
+ALTER TYPE :"schema".content_status_enum OWNER TO oleb;
+
+--
+-- TOC entry 873 (class 1247 OID 42161)
+-- Name: media_type_enum; Type: TYPE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TYPE :"schema".media_type_enum AS ENUM (
+    'image',
+    'pdf',
+    'download',
+    'video'
+);
+
+
+ALTER TYPE :"schema".media_type_enum OWNER TO oleb;
+
+--
+-- TOC entry 876 (class 1247 OID 42170)
+-- Name: page_template_enum; Type: TYPE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TYPE :"schema".page_template_enum AS ENUM (
+    'home',
+    'blog-grid',
+    'category-grid',
+    'article',
+    'content-page',
+    'tool-grid',
+    'contact',
+    'legal'
+);
+
+
+ALTER TYPE :"schema".page_template_enum OWNER TO oleb;
+
+SET default_tablespace = '';
+
+SET default_table_access_method = heap;
+
+--
+-- TOC entry 217 (class 1259 OID 42208)
+-- Name: authors; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".authors (
+    id integer NOT NULL,
+    slug character varying(100) NOT NULL,
+    name character varying(255) NOT NULL,
+    bio text,
+    email character varying(255),
+    active boolean DEFAULT true NOT NULL,
+    created_at timestamp with time zone DEFAULT now() NOT NULL,
+    updated_at timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE :"schema".authors OWNER TO oleb;
+
+--
+-- TOC entry 216 (class 1259 OID 42207)
+-- Name: authors_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".authors_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".authors_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3553 (class 0 OID 0)
+-- Dependencies: 216
+-- Name: authors_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".authors_id_seq OWNED BY :"schema".authors.id;
+
+
+--
+-- TOC entry 234 (class 1259 OID 42396)
+-- Name: build_log; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".build_log (
+    id integer NOT NULL,
+    triggered_by character varying(100),
+    started_at timestamp with time zone DEFAULT now() NOT NULL,
+    finished_at timestamp with time zone,
+    status :"schema".build_status_enum DEFAULT 'running':::"schema".build_status_enum NOT NULL,
+    pages_built integer DEFAULT 0,
+    error_message text
+);
+
+
+ALTER TABLE :"schema".build_log OWNER TO oleb;
+
+--
+-- TOC entry 233 (class 1259 OID 42395)
+-- Name: build_log_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".build_log_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".build_log_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3554 (class 0 OID 0)
+-- Dependencies: 233
+-- Name: build_log_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".build_log_id_seq OWNED BY :"schema".build_log.id;
+
+
+--
+-- TOC entry 221 (class 1259 OID 42241)
+-- Name: categories; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".categories (
+    id integer NOT NULL,
+    slug character varying(100) NOT NULL,
+    label character varying(100) NOT NULL
+);
+
+
+ALTER TABLE :"schema".categories OWNER TO oleb;
+
+--
+-- TOC entry 220 (class 1259 OID 42240)
+-- Name: categories_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".categories_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".categories_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3555 (class 0 OID 0)
+-- Dependencies: 220
+-- Name: categories_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".categories_id_seq OWNED BY :"schema".categories.id;
+
+
+--
+-- TOC entry 232 (class 1259 OID 42380)
+-- Name: content_media; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".content_media (
+    content_id integer NOT NULL,
+    media_id integer NOT NULL,
+    "position" smallint
+);
+
+
+ALTER TABLE :"schema".content_media OWNER TO oleb;
+
+--
+-- TOC entry 230 (class 1259 OID 42350)
+-- Name: content_pages; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".content_pages (
+    content_id integer NOT NULL,
+    category_id integer NOT NULL
+);
+
+
+ALTER TABLE :"schema".content_pages OWNER TO oleb;
+
+--
+-- TOC entry 231 (class 1259 OID 42365)
+-- Name: content_tags; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".content_tags (
+    content_id integer NOT NULL,
+    tag_id integer NOT NULL
+);
+
+
+ALTER TABLE :"schema".content_tags OWNER TO oleb;
+
+--
+-- TOC entry 219 (class 1259 OID 42222)
+-- Name: media; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".media (
+    id integer NOT NULL,
+    path_original character varying(500) NOT NULL,
+    path_webp_lg character varying(500),
+    path_webp_md character varying(500),
+    path_webp_sm character varying(500),
+    filename character varying(255) NOT NULL,
+    media_type :"schema".media_type_enum DEFAULT 'image':::"schema".media_type_enum NOT NULL,
+    mime_type character varying(100),
+    alt_text character varying(500),
+    width_px integer,
+    height_px integer,
+    file_size_bytes bigint,
+    file_hash character varying(64),
+    uploaded_by integer,
+    uploaded_at timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE :"schema".media OWNER TO oleb;
+
+--
+-- TOC entry 218 (class 1259 OID 42221)
+-- Name: media_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".media_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".media_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3556 (class 0 OID 0)
+-- Dependencies: 218
+-- Name: media_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".media_id_seq OWNED BY :"schema".media.id;
+
+
+--
+-- TOC entry 227 (class 1259 OID 42285)
+-- Name: nav_items; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".nav_items (
+    id integer NOT NULL,
+    parent_id integer,
+    page_id integer,
+    external_url character varying(500),
+    label character varying(100) NOT NULL,
+    sort_order smallint DEFAULT 0 NOT NULL,
+    open_new_tab boolean DEFAULT false NOT NULL,
+    active boolean DEFAULT true NOT NULL,
+    CONSTRAINT chk_nav_target CHECK ((((page_id IS NOT NULL) AND (external_url IS NULL)) OR ((page_id IS NULL) AND (external_url IS NOT NULL))))
+);
+
+
+ALTER TABLE :"schema".nav_items OWNER TO oleb;
+
+--
+-- TOC entry 226 (class 1259 OID 42284)
+-- Name: nav_items_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".nav_items_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".nav_items_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3557 (class 0 OID 0)
+-- Dependencies: 226
+-- Name: nav_items_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".nav_items_id_seq OWNED BY :"schema".nav_items.id;
+
+
+--
+-- TOC entry 229 (class 1259 OID 42309)
+-- Name: page_content; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".page_content (
+    id integer NOT NULL,
+    page_id integer NOT NULL,
+    author_id integer,
+    category_id integer,
+    title character varying(255) NOT NULL,
+    subtitle character varying(500),
+    section_label character varying(100),
+    excerpt text,
+    body text,
+    body_secondary text DEFAULT ''::text NOT NULL,
+    hero_media_id integer,
+    card_media_id integer,
+    meta_title character varying(255),
+    meta_desc character varying(320),
+    canonical_url character varying(500),
+    status :"schema".content_status_enum DEFAULT 'draft':::"schema".content_status_enum NOT NULL,
+    publish_at timestamp with time zone,
+    unpublish_at timestamp with time zone,
+    created_at timestamp with time zone DEFAULT now() NOT NULL,
+    updated_at timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE :"schema".page_content OWNER TO oleb;
+
+--
+-- TOC entry 228 (class 1259 OID 42308)
+-- Name: page_content_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".page_content_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".page_content_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3558 (class 0 OID 0)
+-- Dependencies: 228
+-- Name: page_content_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".page_content_id_seq OWNED BY :"schema".page_content.id;
+
+
+--
+-- TOC entry 225 (class 1259 OID 42259)
+-- Name: pages; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".pages (
+    id integer NOT NULL,
+    slug character varying(255) NOT NULL,
+    parent_id integer,
+    template :"schema".page_template_enum DEFAULT 'content-page':::"schema".page_template_enum NOT NULL,
+    sort_order smallint DEFAULT 0 NOT NULL,
+    in_sitemap boolean DEFAULT true NOT NULL,
+    locked_category character varying(100),
+    hero_media_id integer,
+    created_at timestamp with time zone DEFAULT now() NOT NULL,
+    updated_at timestamp with time zone DEFAULT now() NOT NULL
+);
+
+
+ALTER TABLE :"schema".pages OWNER TO oleb;
+
+--
+-- TOC entry 224 (class 1259 OID 42258)
+-- Name: pages_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".pages_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".pages_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3559 (class 0 OID 0)
+-- Dependencies: 224
+-- Name: pages_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".pages_id_seq OWNED BY :"schema".pages.id;
+
+
+--
+-- TOC entry 223 (class 1259 OID 42250)
+-- Name: tags; Type: TABLE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE TABLE :"schema".tags (
+    id integer NOT NULL,
+    slug character varying(100) NOT NULL,
+    label character varying(100) NOT NULL
+);
+
+
+ALTER TABLE :"schema".tags OWNER TO oleb;
+
+--
+-- TOC entry 222 (class 1259 OID 42249)
+-- Name: tags_id_seq; Type: SEQUENCE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE SEQUENCE :"schema".tags_id_seq
+    AS integer
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+ALTER SEQUENCE :"schema".tags_id_seq OWNER TO oleb;
+
+--
+-- TOC entry 3560 (class 0 OID 0)
+-- Dependencies: 222
+-- Name: tags_id_seq; Type: SEQUENCE OWNED BY; Schema: :"schema"; Owner: oleb
+--
+
+ALTER SEQUENCE :"schema".tags_id_seq OWNED BY :"schema".tags.id;
+
+
+--
+-- TOC entry 235 (class 1259 OID 42407)
+-- Name: v_published_content; Type: VIEW; Schema: :"schema"; Owner: oleb
+--
+
+CREATE VIEW :"schema".v_published_content AS
+SELECT
+    NULL::integer AS page_id,
+    NULL::character varying(255) AS slug,
+    NULL::text AS template,
+    NULL::smallint AS sort_order,
+    NULL::character varying(100) AS locked_category,
+    NULL::integer AS content_id,
+    NULL::character varying(255) AS title,
+    NULL::character varying(500) AS subtitle,
+    NULL::character varying(100) AS section_label,
+    NULL::text AS excerpt,
+    NULL::text AS body,
+    NULL::text AS body_secondary,
+    NULL::text AS status,
+    NULL::timestamp with time zone AS publish_at,
+    NULL::timestamp with time zone AS unpublish_at,
+    NULL::timestamp with time zone AS updated_at,
+    NULL::character varying(255) AS meta_title,
+    NULL::character varying(320) AS meta_desc,
+    NULL::character varying(500) AS canonical_url,
+    NULL::character varying(255) AS author_name,
+    NULL::character varying(100) AS author_slug,
+    NULL::character varying(500) AS hero_media_path,
+    NULL::character varying(500) AS hero_media_path_md,
+    NULL::character varying(500) AS hero_alt_text,
+    NULL::character varying(500) AS card_media_path,
+    NULL::character varying(500) AS card_alt_text,
+    NULL::text AS tag_slugs,
+    NULL::text AS tag_labels;
+
+
+ALTER VIEW :"schema".v_published_content OWNER TO oleb;
+
+--
+-- TOC entry 238 (class 1259 OID 42422)
+-- Name: v_blog_cards; Type: VIEW; Schema: :"schema"; Owner: oleb
+--
+
+CREATE VIEW :"schema".v_blog_cards AS
+ SELECT vc.page_id,
+    vc.slug,
+    vc.title,
+    vc.section_label,
+    vc.excerpt,
+    vc.publish_at,
+    vc.updated_at,
+    vc.author_name,
+    vc.card_media_path,
+    vc.card_alt_text,
+    vc.tag_slugs,
+    vc.tag_labels,
+    vc.locked_category,
+    string_agg((c.slug)::text, ','::text ORDER BY (c.slug)::text) AS category_slugs
+   FROM (((:"schema".v_published_content vc
+     JOIN :"schema".page_content pc ON ((pc.id = vc.content_id)))
+     JOIN :"schema".content_pages cp ON ((cp.content_id = pc.id)))
+     JOIN :"schema".categories c ON ((c.id = cp.category_id)))
+  WHERE (vc.template = 'article'::text)
+  GROUP BY vc.page_id, vc.slug, vc.title, vc.section_label, vc.excerpt, vc.publish_at, vc.updated_at, vc.author_name, vc.card_media_path, vc.card_alt_text, vc.tag_slugs, vc.tag_labels, vc.locked_category
+  ORDER BY vc.publish_at DESC NULLS LAST;
+
+
+ALTER VIEW :"schema".v_blog_cards OWNER TO oleb;
+
+--
+-- TOC entry 240 (class 1259 OID 42432)
+-- Name: v_build_status; Type: VIEW; Schema: :"schema"; Owner: oleb
+--
+
+CREATE VIEW :"schema".v_build_status AS
+ SELECT id,
+    triggered_by,
+    started_at,
+    finished_at,
+    (EXTRACT(epoch FROM (finished_at - started_at)))::integer AS duration_seconds,
+    pages_built,
+    status,
+    error_message
+   FROM :"schema".build_log
+  ORDER BY started_at DESC
+ LIMIT 10;
+
+
+ALTER VIEW :"schema".v_build_status OWNER TO oleb;
+
+--
+-- TOC entry 237 (class 1259 OID 42417)
+-- Name: v_nav_tree; Type: VIEW; Schema: :"schema"; Owner: oleb
+--
+
+CREATE VIEW :"schema".v_nav_tree AS
+ SELECT ni.id,
+    ni.parent_id,
+    ni.label,
+    ni.sort_order,
+    ni.open_new_tab,
+        CASE
+            WHEN (ni.external_url IS NOT NULL) THEN (ni.external_url)::text
+            WHEN ((p.slug)::text = 'index'::text) THEN '/'::text
+            ELSE ('/'::text || (p.slug)::text)
+        END AS url
+   FROM (:"schema".nav_items ni
+     LEFT JOIN :"schema".pages p ON ((p.id = ni.page_id)))
+  WHERE (ni.active = true)
+  ORDER BY ni.parent_id NULLS FIRST, ni.sort_order;
+
+
+ALTER VIEW :"schema".v_nav_tree OWNER TO oleb;
+
+--
+-- TOC entry 236 (class 1259 OID 42412)
+-- Name: v_scheduled_due; Type: VIEW; Schema: :"schema"; Owner: oleb
+--
+
+CREATE VIEW :"schema".v_scheduled_due AS
+ SELECT page_id,
+    slug,
+    template,
+    sort_order,
+    locked_category,
+    content_id,
+    title,
+    subtitle,
+    section_label,
+    excerpt,
+    body,
+    body_secondary,
+    status,
+    publish_at,
+    unpublish_at,
+    updated_at,
+    meta_title,
+    meta_desc,
+    canonical_url,
+    author_name,
+    author_slug,
+    hero_media_path,
+    hero_media_path_md,
+    hero_alt_text,
+    card_media_path,
+    card_alt_text,
+    tag_slugs,
+    tag_labels
+   FROM :"schema".v_published_content
+  WHERE ((status = 'scheduled'::text) AND (publish_at <= now()));
+
+
+ALTER VIEW :"schema".v_scheduled_due OWNER TO oleb;
+
+--
+-- TOC entry 239 (class 1259 OID 42427)
+-- Name: v_sitemap; Type: VIEW; Schema: :"schema"; Owner: oleb
+--
+
+CREATE VIEW :"schema".v_sitemap AS
+ SELECT p.slug,
+        CASE
+            WHEN ((p.slug)::text = 'index'::text) THEN '/'::text
+            ELSE ('/'::text || (p.slug)::text)
+        END AS url_path,
+    pc.publish_at AS lastmod,
+        CASE p.template
+            WHEN 'home':::"schema".page_template_enum THEN '1.0'::text
+            WHEN 'blog-grid':::"schema".page_template_enum THEN '0.8'::text
+            WHEN 'article':::"schema".page_template_enum THEN '0.7'::text
+            ELSE '0.5'::text
+        END AS priority
+   FROM (:"schema".pages p
+     JOIN :"schema".page_content pc ON ((pc.page_id = p.id)))
+  WHERE ((pc.status = 'published':::"schema".content_status_enum) AND (p.in_sitemap = true) AND ((pc.unpublish_at IS NULL) OR (pc.unpublish_at > now())))
+  ORDER BY
+        CASE p.template
+            WHEN 'home':::"schema".page_template_enum THEN '1.0'::text
+            WHEN 'blog-grid':::"schema".page_template_enum THEN '0.8'::text
+            WHEN 'article':::"schema".page_template_enum THEN '0.7'::text
+            ELSE '0.5'::text
+        END DESC, pc.publish_at DESC;
+
+
+ALTER VIEW :"schema".v_sitemap OWNER TO oleb;
+
+--
+-- TOC entry 3295 (class 2604 OID 42211)
+-- Name: authors id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".authors ALTER COLUMN id SET DEFAULT nextval(':"schema".authors_id_seq'::regclass);
+
+
+--
+-- TOC entry 3319 (class 2604 OID 42399)
+-- Name: build_log id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".build_log ALTER COLUMN id SET DEFAULT nextval(':"schema".build_log_id_seq'::regclass);
+
+
+--
+-- TOC entry 3302 (class 2604 OID 42244)
+-- Name: categories id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".categories ALTER COLUMN id SET DEFAULT nextval(':"schema".categories_id_seq'::regclass);
+
+
+--
+-- TOC entry 3299 (class 2604 OID 42225)
+-- Name: media id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".media ALTER COLUMN id SET DEFAULT nextval(':"schema".media_id_seq'::regclass);
+
+
+--
+-- TOC entry 3310 (class 2604 OID 42288)
+-- Name: nav_items id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".nav_items ALTER COLUMN id SET DEFAULT nextval(':"schema".nav_items_id_seq'::regclass);
+
+
+--
+-- TOC entry 3314 (class 2604 OID 42312)
+-- Name: page_content id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content ALTER COLUMN id SET DEFAULT nextval(':"schema".page_content_id_seq'::regclass);
+
+
+--
+-- TOC entry 3304 (class 2604 OID 42262)
+-- Name: pages id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".pages ALTER COLUMN id SET DEFAULT nextval(':"schema".pages_id_seq'::regclass);
+
+
+--
+-- TOC entry 3303 (class 2604 OID 42253)
+-- Name: tags id; Type: DEFAULT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".tags ALTER COLUMN id SET DEFAULT nextval(':"schema".tags_id_seq'::regclass);
+
+
+
+
+--
+-- TOC entry 3325 (class 2606 OID 42218)
+-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".authors
+    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3327 (class 2606 OID 42220)
+-- Name: authors authors_slug_key; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".authors
+    ADD CONSTRAINT authors_slug_key UNIQUE (slug);
+
+
+--
+-- TOC entry 3363 (class 2606 OID 42406)
+-- Name: build_log build_log_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".build_log
+    ADD CONSTRAINT build_log_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3334 (class 2606 OID 42246)
+-- Name: categories categories_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".categories
+    ADD CONSTRAINT categories_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3336 (class 2606 OID 42248)
+-- Name: categories categories_slug_key; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".categories
+    ADD CONSTRAINT categories_slug_key UNIQUE (slug);
+
+
+--
+-- TOC entry 3361 (class 2606 OID 42384)
+-- Name: content_media content_media_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_media
+    ADD CONSTRAINT content_media_pkey PRIMARY KEY (content_id, media_id);
+
+
+--
+-- TOC entry 3357 (class 2606 OID 42354)
+-- Name: content_pages content_pages_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_pages
+    ADD CONSTRAINT content_pages_pkey PRIMARY KEY (content_id, category_id);
+
+
+--
+-- TOC entry 3359 (class 2606 OID 42369)
+-- Name: content_tags content_tags_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_tags
+    ADD CONSTRAINT content_tags_pkey PRIMARY KEY (content_id, tag_id);
+
+
+--
+-- TOC entry 3330 (class 2606 OID 42233)
+-- Name: media media_path_original_key; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".media
+    ADD CONSTRAINT media_path_original_key UNIQUE (path_original);
+
+
+--
+-- TOC entry 3332 (class 2606 OID 42231)
+-- Name: media media_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".media
+    ADD CONSTRAINT media_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3349 (class 2606 OID 42296)
+-- Name: nav_items nav_items_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".nav_items
+    ADD CONSTRAINT nav_items_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3355 (class 2606 OID 42320)
+-- Name: page_content page_content_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content
+    ADD CONSTRAINT page_content_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3344 (class 2606 OID 42269)
+-- Name: pages pages_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".pages
+    ADD CONSTRAINT pages_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3346 (class 2606 OID 42271)
+-- Name: pages pages_slug_key; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".pages
+    ADD CONSTRAINT pages_slug_key UNIQUE (slug);
+
+
+--
+-- TOC entry 3338 (class 2606 OID 42255)
+-- Name: tags tags_pkey; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".tags
+    ADD CONSTRAINT tags_pkey PRIMARY KEY (id);
+
+
+--
+-- TOC entry 3340 (class 2606 OID 42257)
+-- Name: tags tags_slug_key; Type: CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".tags
+    ADD CONSTRAINT tags_slug_key UNIQUE (slug);
+
+
+--
+-- TOC entry 3350 (class 1259 OID 42349)
+-- Name: idx_content_category; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_content_category ON :"schema".page_content USING btree (category_id);
+
+
+--
+-- TOC entry 3351 (class 1259 OID 42346)
+-- Name: idx_content_page; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_content_page ON :"schema".page_content USING btree (page_id);
+
+
+--
+-- TOC entry 3352 (class 1259 OID 42348)
+-- Name: idx_content_publish; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_content_publish ON :"schema".page_content USING btree (publish_at) WHERE (status = 'scheduled':::"schema".content_status_enum);
+
+
+--
+-- TOC entry 3353 (class 1259 OID 42347)
+-- Name: idx_content_status; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_content_status ON :"schema".page_content USING btree (status);
+
+
+--
+-- TOC entry 3328 (class 1259 OID 42239)
+-- Name: idx_media_hash; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_media_hash ON :"schema".media USING btree (file_hash);
+
+
+--
+-- TOC entry 3347 (class 1259 OID 42307)
+-- Name: idx_nav_parent; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_nav_parent ON :"schema".nav_items USING btree (parent_id, sort_order);
+
+
+--
+-- TOC entry 3341 (class 1259 OID 42282)
+-- Name: idx_pages_parent; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_pages_parent ON :"schema".pages USING btree (parent_id);
+
+
+--
+-- TOC entry 3342 (class 1259 OID 42283)
+-- Name: idx_pages_sort; Type: INDEX; Schema: :"schema"; Owner: oleb
+--
+
+CREATE INDEX idx_pages_sort ON :"schema".pages USING btree (parent_id, sort_order);
+
+
+--
+-- TOC entry 3523 (class 2618 OID 42410)
+-- Name: v_published_content _RETURN; Type: RULE; Schema: :"schema"; Owner: oleb
+--
+
+CREATE OR REPLACE VIEW :"schema".v_published_content AS
+ SELECT p.id AS page_id,
+    p.slug,
+    (p.template)::text AS template,
+    p.sort_order,
+    p.locked_category,
+    pc.id AS content_id,
+    pc.title,
+    pc.subtitle,
+    pc.section_label,
+    pc.excerpt,
+    pc.body,
+    pc.body_secondary,
+    (pc.status)::text AS status,
+    pc.publish_at,
+    pc.unpublish_at,
+    pc.updated_at,
+    pc.meta_title,
+    pc.meta_desc,
+    pc.canonical_url,
+    a.name AS author_name,
+    a.slug AS author_slug,
+    hero.path_webp_lg AS hero_media_path,
+    hero.path_webp_md AS hero_media_path_md,
+    hero.alt_text AS hero_alt_text,
+    card.path_webp_sm AS card_media_path,
+    card.alt_text AS card_alt_text,
+    string_agg((t.slug)::text, ','::text ORDER BY t.label) AS tag_slugs,
+    string_agg((t.label)::text, ','::text ORDER BY (t.label)::text) AS tag_labels
+   FROM ((((((:"schema".pages p
+     JOIN :"schema".page_content pc ON ((pc.page_id = p.id)))
+     LEFT JOIN :"schema".authors a ON ((a.id = pc.author_id)))
+     LEFT JOIN :"schema".media hero ON ((hero.id = pc.hero_media_id)))
+     LEFT JOIN :"schema".media card ON ((card.id = pc.card_media_id)))
+     LEFT JOIN :"schema".content_tags ct ON ((ct.content_id = pc.id)))
+     LEFT JOIN :"schema".tags t ON ((t.id = ct.tag_id)))
+  WHERE ((pc.status = 'published':::"schema".content_status_enum) AND ((pc.unpublish_at IS NULL) OR (pc.unpublish_at > now())))
+  GROUP BY p.id, p.slug, p.template, p.sort_order, p.locked_category, pc.id, pc.title, pc.subtitle, pc.section_label, pc.excerpt, pc.body, pc.body_secondary, pc.status, pc.publish_at, pc.unpublish_at, pc.meta_title, pc.meta_desc, pc.canonical_url, a.name, a.slug, hero.path_webp_lg, hero.path_webp_md, hero.alt_text, card.path_webp_sm, card.alt_text;
+
+
+--
+-- TOC entry 3378 (class 2606 OID 42385)
+-- Name: content_media content_media_content_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_media
+    ADD CONSTRAINT content_media_content_id_fkey FOREIGN KEY (content_id) REFERENCES :"schema".page_content(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3379 (class 2606 OID 42390)
+-- Name: content_media content_media_media_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_media
+    ADD CONSTRAINT content_media_media_id_fkey FOREIGN KEY (media_id) REFERENCES :"schema".media(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3374 (class 2606 OID 42360)
+-- Name: content_pages content_pages_category_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_pages
+    ADD CONSTRAINT content_pages_category_id_fkey FOREIGN KEY (category_id) REFERENCES :"schema".categories(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3375 (class 2606 OID 42355)
+-- Name: content_pages content_pages_content_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_pages
+    ADD CONSTRAINT content_pages_content_id_fkey FOREIGN KEY (content_id) REFERENCES :"schema".page_content(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3376 (class 2606 OID 42370)
+-- Name: content_tags content_tags_content_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_tags
+    ADD CONSTRAINT content_tags_content_id_fkey FOREIGN KEY (content_id) REFERENCES :"schema".page_content(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3377 (class 2606 OID 42375)
+-- Name: content_tags content_tags_tag_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".content_tags
+    ADD CONSTRAINT content_tags_tag_id_fkey FOREIGN KEY (tag_id) REFERENCES :"schema".tags(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3364 (class 2606 OID 42234)
+-- Name: media media_uploaded_by_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".media
+    ADD CONSTRAINT media_uploaded_by_fkey FOREIGN KEY (uploaded_by) REFERENCES :"schema".authors(id) ON DELETE SET NULL;
+
+
+--
+-- TOC entry 3367 (class 2606 OID 42302)
+-- Name: nav_items nav_items_page_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".nav_items
+    ADD CONSTRAINT nav_items_page_id_fkey FOREIGN KEY (page_id) REFERENCES :"schema".pages(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3368 (class 2606 OID 42297)
+-- Name: nav_items nav_items_parent_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".nav_items
+    ADD CONSTRAINT nav_items_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES :"schema".nav_items(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3369 (class 2606 OID 42326)
+-- Name: page_content page_content_author_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content
+    ADD CONSTRAINT page_content_author_id_fkey FOREIGN KEY (author_id) REFERENCES :"schema".authors(id) ON DELETE SET NULL;
+
+
+--
+-- TOC entry 3370 (class 2606 OID 42341)
+-- Name: page_content page_content_card_media_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content
+    ADD CONSTRAINT page_content_card_media_id_fkey FOREIGN KEY (card_media_id) REFERENCES :"schema".media(id) ON DELETE SET NULL;
+
+
+--
+-- TOC entry 3371 (class 2606 OID 42331)
+-- Name: page_content page_content_category_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content
+    ADD CONSTRAINT page_content_category_id_fkey FOREIGN KEY (category_id) REFERENCES :"schema".categories(id) ON DELETE SET NULL;
+
+
+--
+-- TOC entry 3372 (class 2606 OID 42336)
+-- Name: page_content page_content_hero_media_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content
+    ADD CONSTRAINT page_content_hero_media_id_fkey FOREIGN KEY (hero_media_id) REFERENCES :"schema".media(id) ON DELETE SET NULL;
+
+
+--
+-- TOC entry 3373 (class 2606 OID 42321)
+-- Name: page_content page_content_page_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".page_content
+    ADD CONSTRAINT page_content_page_id_fkey FOREIGN KEY (page_id) REFERENCES :"schema".pages(id) ON DELETE CASCADE;
+
+
+--
+-- TOC entry 3365 (class 2606 OID 42277)
+-- Name: pages pages_hero_media_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".pages
+    ADD CONSTRAINT pages_hero_media_id_fkey FOREIGN KEY (hero_media_id) REFERENCES :"schema".media(id) ON DELETE SET NULL;
+
+
+--
+-- TOC entry 3366 (class 2606 OID 42272)
+-- Name: pages pages_parent_id_fkey; Type: FK CONSTRAINT; Schema: :"schema"; Owner: oleb
+--
+
+ALTER TABLE ONLY :"schema".pages
+    ADD CONSTRAINT pages_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES :"schema".pages(id) ON DELETE SET NULL;
+
+
+-- Completed on 2026-03-18 13:41:21 CET
+
+--
+-- PostgreSQL database dump complete
+--
+
diff --git a/db/dump-laktatnebel-202603181342_data.sql b/db/dump-laktatnebel-202603181342_data.sql
new file mode 100644 (file)
index 0000000..58b38b9
--- /dev/null
@@ -0,0 +1,79 @@
+
+SET search_path TO :"schema";
+
+
+--
+-- TOC entry 3530 (class 0 OID 42208)
+-- Dependencies: 217
+-- Data for Name: authors; Type: TABLE DATA; Schema: :"schema"; Owner: oleb
+--
+
+INSERT INTO :"schema".authors VALUES (1, 'coach', 'Triathlon-Coach', 'Seit 1987 Läufer, seit 1997 Triathlet – leistungssportlich zwischen 800m und Ironman. Lizensierter DTU-C-Trainer seit 2018.', NULL, true, '2026-03-15 22:06:02.207721+01', '2026-03-15 22:06:02.207721+01');
+
+
+--
+-- TOC entry 3534 (class 0 OID 42241)
+-- Dependencies: 221
+-- Data for Name: categories; Type: TABLE DATA; Schema: :"schema"; Owner: oleb
+--
+
+INSERT INTO :"schema".categories VALUES (DEFAULT, 'blog', 'Blog');
+INSERT INTO :"schema".categories VALUES (DEFAULT, 'coaching', 'Coaching');
+INSERT INTO :"schema".categories VALUES (DEFAULT, 'angebot', 'Angebot');
+
+
+
+--
+-- TOC entry 3536 (class 0 OID 42250)
+-- Dependencies: 223
+-- Data for Name: tags; Type: TABLE DATA; Schema: :"schema"; Owner: oleb
+--
+
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'training', 'Training');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'ernaehrung', 'Ernährung');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'regeneration', 'Regeneration');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'gesundheit', 'Gesundheit');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'raceday', 'Raceday');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'running', 'Running');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'bike', 'Bike');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'lifestyle', 'Lifestyle');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'saisonplanung', 'Saisonplanung');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'equipment', 'Equipment');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'athletik', 'Athletik');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'camp', 'Camp');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'fatmax', 'FatMax');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'fueling', 'Fueling');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'ironman', 'Ironman');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'k3', 'K3');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'kohlenhydrate', 'Kohlenhydrate');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'kraft', 'Kraft');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'kraftausdauer', 'Kraftausdauer');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'krafttraining', 'Krafttraining');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'langdistanz', 'Langdistanz');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'marathon', 'Marathon');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'mindset', 'Mindset');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'mitteldistanz', 'Mitteldistanz');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'motivation', 'Motivation');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'offseason', 'Offseason');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'openwater', 'Openwater');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'pacing', 'Pacing');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'proteine', 'Proteine');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'psyche', 'Psyche');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'racing', 'Racing');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'radfahren', 'Radfahren');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'rennrad', 'Rennrad');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'szene', 'Szene');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'swim', 'Swim');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'taktik', 'Taktik');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'technik', 'Technik');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'tempo', 'Tempo');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'triathlon', 'Triathlon');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'coaching', 'Coaching');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'leichtathletik', 'Leichtathletik');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'duathlon', 'Duathlon');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'skilanglauf', 'Ski-Langlauf');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'mtb', 'MTB');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'cyclocross', 'Cyclocross/Gravel');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'radsport', 'Radsport');
+INSERT INTO :"schema".tags VALUES (DEFAULT, 'fairplay', 'Fairplay');
+