diff --git a/src/app/features/[slug]/page.tsx b/src/app/features/[slug]/page.tsx new file mode 100644 index 0000000..f51df8b --- /dev/null +++ b/src/app/features/[slug]/page.tsx @@ -0,0 +1,327 @@ +import type { Metadata } from "next"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { + ArrowLeft, + ArrowRight, + CheckCircle2, + HelpCircle, + ShieldCheck, +} from "lucide-react"; + +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + getMarketingFeature, + marketingFeatures, +} from "@/lib/marketing/features"; + +type FeaturePageProps = { + params: Promise<{ + slug: string; + }>; +}; + +export const dynamicParams = false; + +export function generateStaticParams() { + return marketingFeatures.map((feature) => ({ + slug: feature.slug, + })); +} + +export async function generateMetadata({ + params, +}: FeaturePageProps): Promise { + const { slug } = await params; + const feature = getMarketingFeature(slug); + + if (!feature) { + return { + title: "Feature nicht gefunden", + }; + } + + return { + title: feature.seoTitle, + description: feature.seoDescription, + openGraph: { + title: feature.seoTitle, + description: feature.seoDescription, + type: "website", + locale: "de_DE", + images: [ + { + url: "/og-image.png", + width: 1200, + height: 630, + alt: "Ein Kind spielt mit bunten Holzklötzen.", + }, + ], + }, + twitter: { + card: "summary_large_image", + title: feature.seoTitle, + description: feature.seoDescription, + images: ["/og-image.png"], + }, + }; +} + +export default async function FeaturePage({ params }: FeaturePageProps) { + const { slug } = await params; + const feature = getMarketingFeature(slug); + + if (!feature) { + notFound(); + } + + const Icon = feature.icon; + + return ( +
+
+
+ + + + + + Kita-Planer + + + + +
+
+ +
+
+
+
+ + + + {feature.eyebrow} + +

+ {feature.heroTitle} +

+

+ {feature.heroDescription} +

+
+ + +
+
+ +
+
+ +
+

+ In einem Satz +

+

+ {feature.description} +

+
+ {feature.benefits.slice(0, 3).map((benefit) => ( +
+ + {benefit.title} +
+ ))} +
+
+
+
+ +
+ + + + {feature.problemTitle} + + + {feature.problemText} + + + + + + + + {feature.solutionTitle} + + + {feature.solutionText} + + + +
+ +
+
+
+

+ Was das konkret bringt +

+

+ Weniger Abstimmungslast, mehr Klarheit im Kita-Alltag. +

+
+ +
+ {feature.benefits.map((benefit) => ( + + +
+ +
+ + {benefit.title} + + + {benefit.text} + +
+
+ ))} +
+
+
+ +
+
+
+ + Vertrauen & Datenschutz + +

+ {feature.trustTitle} +

+

+ {feature.trustText} +

+
+ +
+
+ +
+
+

+ Fragen aus dem Vorstand +

+

+ Kurz beantwortet. +

+
+ +
+ {feature.faqs.map((faq) => ( + + +
+ +
+ + {faq.question} + + + {faq.answer} + +
+
+ ))} +
+
+ +
+
+
+

+ Wollt ihr {feature.shortTitle} im echten Kita-Alltag sehen? +

+

+ Schreibt uns kurz, wie ihr heute organisiert seid. Wir zeigen + euch, wie Kita-Planer zu eurem Elternverein passen kann. +

+
+ +
+
+
+ +
+
+ © {new Date().getFullYear()} Kita-Planer + +
+
+
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 46c1e5d..be46ef6 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -3,19 +3,14 @@ import Link from "next/link"; import { redirect } from "next/navigation"; import { ArrowRight, - CalendarDays, CheckCircle2, DatabaseZap, Fingerprint, LockKeyhole, Mail, - Megaphone, MessageSquareText, - ShieldAlert, ShieldCheck, - Stethoscope, Trash2, - UsersRound, } from "lucide-react"; import { auth } from "@/auth"; @@ -28,6 +23,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { marketingFeatures } from "@/lib/marketing/features"; import { ContactForm } from "./contact-form"; export const metadata: Metadata = { @@ -61,46 +57,6 @@ export const metadata: Metadata = { const heroImage = "https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?auto=format&fit=crop&w=2400&q=86"; -const features = [ - { - icon: ShieldAlert, - title: "Fairer Notdienst-Planer", - description: - "Automatische Generierung, gerechte Verteilung und 1-Klick-Alarmierung, wenn morgens Ersatz gebraucht wird.", - accent: "bg-red-50 text-red-700 ring-red-100", - }, - { - icon: CalendarDays, - title: "Smarter Kalender", - description: - "Feste, Termine, Raumbuchungen und digitale Mitbring-Listen in einem verbindlichen Kalender für alle Familien.", - accent: "bg-sky-50 text-sky-700 ring-sky-100", - }, - { - icon: UsersRound, - title: "Sicheres Adressbuch", - description: - "Haushaltsbasiert, DSGVO-konform und mit strengem Opt-In: Kontaktdaten werden nur sichtbar, wenn Eltern zustimmen.", - accent: "bg-emerald-50 text-emerald-700 ring-emerald-100", - }, - { - icon: Stethoscope, - title: "Digitale Krankmeldung", - description: - "Ein Klick statt Dauerläuten am Morgen. Eltern melden Kinder digital ab, ErzieherInnen sehen auf dem Tablet sofort den Überblick für den Morgenkreis.", - accent: "bg-amber-50 text-amber-700 ring-amber-100", - badge: "Neu", - }, - { - icon: Megaphone, - title: "Schwarzes Brett", - description: - "Der WhatsApp-Killer für Vorstände: offizielle Ankündigungen mit Dateianhängen, Lesebestätigung und optionalem E-Mail-Push.", - accent: "bg-indigo-50 text-indigo-700 ring-indigo-100", - badge: "Neu", - }, -]; - const privacyPoints = [ { icon: DatabaseZap, @@ -246,7 +202,7 @@ export default async function LandingPage() {
- {features.map((feature, index) => { + {marketingFeatures.map((feature, index) => { const Icon = feature.icon; const isWide = index > 2; return ( @@ -276,6 +232,16 @@ export default async function LandingPage() { {feature.description} +
diff --git a/src/app/robots.ts b/src/app/robots.ts index 9aec5cf..37259c1 100644 --- a/src/app/robots.ts +++ b/src/app/robots.ts @@ -10,7 +10,7 @@ export default function robots(): MetadataRoute.Robots { return { rules: { userAgent: "*", - allow: ["/", "/impressum", "/datenschutz"], + allow: ["/", "/features/", "/impressum", "/datenschutz"], disallow: [ "/api/", "/dashboard/", diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 560dca3..0167d81 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -1,5 +1,7 @@ import type { MetadataRoute } from "next"; +import { marketingFeatures } from "@/lib/marketing/features"; + function getSiteUrl() { return process.env.NEXT_PUBLIC_SITE_URL ?? "https://mein-kitaplaner.de"; } @@ -27,5 +29,11 @@ export default function sitemap(): MetadataRoute.Sitemap { changeFrequency: "yearly", priority: 0.2, }, + ...marketingFeatures.map((feature) => ({ + url: `${siteUrl}/features/${feature.slug}`, + lastModified, + changeFrequency: "monthly" as const, + priority: 0.8, + })), ]; } diff --git a/src/components/analytics/umami-analytics.tsx b/src/components/analytics/umami-analytics.tsx index 8205a3f..9b6f3d1 100644 --- a/src/components/analytics/umami-analytics.tsx +++ b/src/components/analytics/umami-analytics.tsx @@ -1,11 +1,14 @@ import Script from "next/script"; +import { marketingFeatureSlugs } from "@/lib/marketing/features"; + const publicAnalyticsPaths = new Set([ "/", "/impressum", "/datenschutz", "/login", "/register", + ...marketingFeatureSlugs.map((slug) => `/features/${slug}`), ]); export function UmamiAnalytics() { diff --git a/src/lib/marketing/features.ts b/src/lib/marketing/features.ts new file mode 100644 index 0000000..901b19d --- /dev/null +++ b/src/lib/marketing/features.ts @@ -0,0 +1,350 @@ +import type { LucideIcon } from "lucide-react"; +import { + CalendarDays, + Megaphone, + ShieldAlert, + Stethoscope, + UsersRound, +} from "lucide-react"; + +export type MarketingFeature = { + slug: string; + icon: LucideIcon; + title: string; + shortTitle: string; + description: string; + accent: string; + badge?: string; + eyebrow: string; + heroTitle: string; + heroDescription: string; + seoTitle: string; + seoDescription: string; + problemTitle: string; + problemText: string; + solutionTitle: string; + solutionText: string; + benefits: { + title: string; + text: string; + }[]; + trustTitle: string; + trustText: string; + faqs: { + question: string; + answer: string; + }[]; +}; + +export const marketingFeatures: MarketingFeature[] = [ + { + slug: "notdienst-planer", + icon: ShieldAlert, + title: "Fairer Notdienst-Planer", + shortTitle: "Notdienst-Planer", + description: + "Automatische Generierung, gerechte Verteilung und 1-Klick-Alarmierung, wenn morgens Ersatz gebraucht wird.", + accent: "bg-red-50 text-red-700 ring-red-100", + eyebrow: "Notdienst ohne Excel-Lotterie", + heroTitle: "Faire Notdienstplanung für Elterninitiativen.", + heroDescription: + "Eltern tragen ihre Verfügbarkeiten ein, Vorstände behalten den Überblick und der Monatsplan entsteht nachvollziehbar statt in endlosen Chatverläufen.", + seoTitle: "Notdienst-Planer für Kita-Elternvereine", + seoDescription: + "Plant Notdienste fair, digital und nachvollziehbar: Verfügbarkeiten erfassen, Mindesttage berücksichtigen und Ersatz schneller finden.", + problemTitle: "Wenn morgens plötzlich Ersatz gebraucht wird", + problemText: + "In vielen Elterninitiativen hängt der Notdienst an Tabellen, Bauchgefühl und der Hoffnung, dass irgendwer im Chat rechtzeitig reagiert. Das ist für Vorstände anstrengend und für Eltern oft schwer nachvollziehbar.", + solutionTitle: "Verfügbarkeiten einsammeln, Plan erzeugen, reagieren", + solutionText: + "Kita-Planer bündelt die Verfügbarkeiten der Familien, berücksichtigt Mindesttage pro Kind und unterstützt Koordinatoren dabei, den Monatsplan zu erstellen und bei Ausfällen schneller Ersatz zu finden.", + benefits: [ + { + title: "Verfügbarkeiten pro Familie", + text: "Eltern geben digital an, an welchen Tagen sie unterstützen können. Der Vorstand arbeitet mit strukturierten Daten statt verstreuten Nachrichten.", + }, + { + title: "Nachvollziehbare Verteilung", + text: "Mindesttage pro Kind und aktive Kinder werden berücksichtigt, damit die Planung transparent und fairer erklärbar bleibt.", + }, + { + title: "Planung für Koordinatoren", + text: "Koordinatoren sehen den Zielmonat, können Pläne erzeugen und bei Bedarf manuell nachsteuern.", + }, + { + title: "Schneller reagieren", + text: "Wenn morgens Ersatz nötig ist, hilft eine strukturierte Übersicht deutlich mehr als ein hektischer Chat.", + }, + ], + trustTitle: "Gemacht für sensible Kita-Abläufe", + trustText: + "Notdienst-Daten bleiben im geschützten Kita-Kontext und sind an Rollenrechte sowie die jeweilige Kita-Zugehörigkeit gebunden.", + faqs: [ + { + question: "Können Eltern selbst eintragen, wann sie verfügbar sind?", + answer: + "Ja. Eltern können ihre möglichen Notdiensttage für den Zielmonat digital hinterlegen.", + }, + { + question: "Kann der Vorstand den Plan noch anpassen?", + answer: + "Ja. Koordinatoren und Admins behalten die Übersicht und können bei Bedarf manuell nachsteuern.", + }, + { + question: "Ersetzt das alle Abstimmungen im Notfall?", + answer: + "Nein, aber es schafft eine deutlich bessere Grundlage, um schnell passende Familien zu finden.", + }, + ], + }, + { + slug: "kita-kalender", + icon: CalendarDays, + title: "Smarter Kalender", + shortTitle: "Kita-Kalender", + description: + "Feste, Termine, Raumbuchungen und digitale Mitbring-Listen in einem verbindlichen Kalender für alle Familien.", + accent: "bg-sky-50 text-sky-700 ring-sky-100", + eyebrow: "Termine, Dienste und Mitbringlisten", + heroTitle: "Ein Kita-Kalender, den Eltern wirklich nutzen.", + heroDescription: + "Alle wichtigen Termine, Dienstzuordnungen und Mitbringlisten an einem Ort, damit niemand nach der richtigen Nachricht im Chat suchen muss.", + seoTitle: "Kita-Kalender für Elternvereine", + seoDescription: + "Ein gemeinsamer Kalender für Elterninitiativen: Termine, Anfragen, Dienste und Mitbringlisten übersichtlich organisieren.", + problemTitle: "Termine verschwinden zu schnell", + problemText: + "Elternabende, Feste, Schließtage, Dienste und Mitbringlisten landen oft in unterschiedlichen Kanälen. Wer später nachschaut, findet nicht mehr sicher die aktuelle Information.", + solutionTitle: "Ein verbindlicher Ort für den Kita-Alltag", + solutionText: + "Kita-Planer zeigt bestätigte Termine, eigene Anfragen, Dienstzuordnungen und Mitbringlisten gemeinsam. Admins können Anfragen prüfen und offizielle Termine sauber veröffentlichen.", + benefits: [ + { + title: "Termine im Überblick", + text: "Feste, Schließtage, Elternabende und andere Ereignisse werden zentral sichtbar.", + }, + { + title: "Anfragen statt Nebenabsprachen", + text: "Eltern können Terminwünsche einreichen, die von Verantwortlichen geprüft werden.", + }, + { + title: "Mitbringlisten direkt am Termin", + text: "Was gebraucht wird, steht dort, wo Eltern es erwarten: am passenden Termin.", + }, + { + title: "Dienste sichtbar machen", + text: "Geplante Dienste werden im Kontext der kommenden Termine und Aufgaben angezeigt.", + }, + ], + trustTitle: "Verbindlichkeit statt Chat-Suche", + trustText: + "Der Kalender ist Teil des geschützten Kita-Bereichs und zeigt Informationen rollen- und mandantenbezogen an.", + faqs: [ + { + question: "Können Eltern eigene Termine vorschlagen?", + answer: + "Ja. Terminanfragen können eingereicht und von berechtigten Personen geprüft werden.", + }, + { + question: "Sind Mitbringlisten enthalten?", + answer: + "Ja. Termine können mit digitalen Mitbringlisten verbunden werden.", + }, + { + question: "Wer sieht welche Termine?", + answer: + "Termine werden innerhalb der jeweiligen Kita angezeigt; Admins und Koordinatoren haben zusätzliche Prüf- und Verwaltungsfunktionen.", + }, + ], + }, + { + slug: "eltern-adressbuch", + icon: UsersRound, + title: "Sicheres Adressbuch", + shortTitle: "Eltern-Adressbuch", + description: + "Haushaltsbasiert, DSGVO-konform gedacht und mit strengem Opt-In: Kontaktdaten werden nur sichtbar, wenn Eltern zustimmen.", + accent: "bg-emerald-50 text-emerald-700 ring-emerald-100", + eyebrow: "Kontakte nur mit Zustimmung", + heroTitle: "Ein Eltern-Adressbuch mit klarer Freigabe.", + heroDescription: + "Kontaktdaten werden nicht einfach herumgereicht, sondern nur sichtbar, wenn Eltern aktiv zustimmen.", + seoTitle: "Sicheres Eltern-Adressbuch für Kitas", + seoDescription: + "Ein digitales Kita-Adressbuch mit Opt-in, Haushalten und freigegebenen Kontaktdaten für Elternvereine und Elterninitiativen.", + problemTitle: "Kontaktlisten sind praktisch, aber sensibel", + problemText: + "Spielverabredungen und schnelle Rückfragen brauchen Kontaktdaten. Gleichzeitig möchten Eltern selbst entscheiden, welche Daten sichtbar sind.", + solutionTitle: "Haushalte, Kinder und Freigaben sauber trennen", + solutionText: + "Kita-Planer zeigt Familien und Kontaktdaten nur, wenn mindestens ein Elternteil aktiv zugestimmt hat. Nicht freigegebene Daten bleiben verborgen.", + benefits: [ + { + title: "Opt-in statt Rundmail", + text: "Eltern geben bewusst frei, ob ihre Kontaktdaten im internen Adressbuch erscheinen.", + }, + { + title: "Haushalte im Blick", + text: "Familien, Kinder und Elternteile werden gemeinsam verständlich dargestellt.", + }, + { + title: "Nur freigegebene Daten", + text: "E-Mail und Telefonnummer werden nur dort angezeigt, wo eine Freigabe vorliegt.", + }, + { + title: "Hilfreich für Dienste", + text: "Zugeordnete Elternaufgaben und Familieninformationen können im passenden Kontext sichtbar werden.", + }, + ], + trustTitle: "Datenschutz ist Teil der Funktion", + trustText: + "Das Adressbuch ist bewusst als Opt-in-Funktion gestaltet. Es ersetzt lose Listen durch kontrollierte Sichtbarkeit.", + faqs: [ + { + question: "Sind alle Eltern automatisch sichtbar?", + answer: + "Nein. Kontaktdaten erscheinen nur nach aktiver Freigabe.", + }, + { + question: "Kann eine Familie teilweise sichtbar sein?", + answer: + "Ja. Sichtbarkeit hängt an den freigegebenen Elternteilen und deren Daten.", + }, + { + question: "Ist das eine Rechtsberatung zur DSGVO?", + answer: + "Nein. Kita-Planer ist datensparsam gedacht, ersetzt aber keine rechtliche Prüfung eurer konkreten Prozesse.", + }, + ], + }, + { + slug: "krankmeldung", + icon: Stethoscope, + title: "Digitale Krankmeldung", + shortTitle: "Krankmeldung", + description: + "Ein Klick statt Dauerläuten am Morgen. Eltern melden Kinder digital ab, ErzieherInnen sehen sofort den Überblick.", + accent: "bg-amber-50 text-amber-700 ring-amber-100", + badge: "Neu", + eyebrow: "Abwesenheiten ohne Telefonkette", + heroTitle: "Krankmeldungen digital und morgens sofort sichtbar.", + heroDescription: + "Eltern melden Abwesenheiten digital, das Team sieht den Tagesüberblick und der Morgen startet mit weniger Telefonchaos.", + seoTitle: "Digitale Krankmeldung für Kitas", + seoDescription: + "Eltern melden Kinder digital krank oder abwesend. Kita-Teams behalten den Tagesüberblick ohne Telefonchaos am Morgen.", + problemTitle: "Der Morgen beginnt oft mit Dauerläuten", + problemText: + "Wenn mehrere Kinder fehlen, sammeln sich Telefonate, Chatnachrichten und Zurufe genau dann, wenn das Team eigentlich den Tag vorbereiten muss.", + solutionTitle: "Abwesenheiten dort erfassen, wo sie gebraucht werden", + solutionText: + "Kita-Planer bündelt digitale Abwesenheitsmeldungen je Kita und zeigt sie im Dashboard, damit Team und Vorstand schneller den Überblick haben.", + benefits: [ + { + title: "Eltern melden digital", + text: "Abwesenheiten können strukturiert mit Zeitraum und Grund hinterlegt werden.", + }, + { + title: "Tagesüberblick fürs Team", + text: "ErzieherInnen sehen, welche Kinder fehlen, ohne Telefonnotizen zusammenzutragen.", + }, + { + title: "Weniger Missverständnisse", + text: "Zeiträume und Hinweise sind dokumentiert, statt in einzelnen Chatnachrichten zu verschwinden.", + }, + { + title: "Passt zum Familienprofil", + text: "Abwesenheiten sind mit den Kindern und der jeweiligen Kita-Zugehörigkeit verbunden.", + }, + ], + trustTitle: "Sensible Informationen geschützt behandeln", + trustText: + "Abwesenheiten sind personenbezogene Informationen. Kita-Planer behandelt sie innerhalb des geschützten Kita-Bereichs und nicht als öffentliche Nachricht.", + faqs: [ + { + question: "Können Eltern mehrere Tage eintragen?", + answer: + "Ja. Abwesenheiten können für einen Zeitraum erfasst werden.", + }, + { + question: "Sieht das Kita-Team die Meldungen sofort?", + answer: + "Die Meldungen werden im System sichtbar und können im Dashboard ausgewertet werden.", + }, + { + question: "Ersetzt das jede telefonische Rückfrage?", + answer: + "Nicht jede. Bei besonderen Situationen kann weiterhin persönlich nachgefragt werden.", + }, + ], + }, + { + slug: "schwarzes-brett", + icon: Megaphone, + title: "Schwarzes Brett", + shortTitle: "Schwarzes Brett", + description: + "Offizielle Ankündigungen mit Dateianhängen, Lesebestätigung und optionalem E-Mail-Push statt verstreuter Chatposts.", + accent: "bg-indigo-50 text-indigo-700 ring-indigo-100", + badge: "Neu", + eyebrow: "Verbindliche Kita-Kommunikation", + heroTitle: "Ein digitales Schwarzes Brett für offizielle Nachrichten.", + heroDescription: + "Vorstände veröffentlichen Ankündigungen, hängen Dokumente an und erreichen Eltern über einen klaren Kanal statt über mehrere Chatgruppen.", + seoTitle: "Digitales Schwarzes Brett für Kitas", + seoDescription: + "Offizielle Ankündigungen für Elternvereine: Nachrichten, Anhänge, Lesestatus und optionaler E-Mail-Push in einem geschützten System.", + problemTitle: "Wichtige Infos gehen im Chat unter", + problemText: + "Zwischen Fotos, Rückfragen und spontanen Abstimmungen verlieren offizielle Ankündigungen schnell ihre Sichtbarkeit.", + solutionTitle: "Ein Kanal für das, was verbindlich sein soll", + solutionText: + "Kita-Planer trennt offizielle Nachrichten vom Chatrauschen. Ankündigungen können Anhänge enthalten und sind für die passende Kita geschützt abrufbar.", + benefits: [ + { + title: "Offizielle Ankündigungen", + text: "Vorstände und Admins veröffentlichen zentrale Nachrichten an Eltern oder Team.", + }, + { + title: "Geschützte Anhänge", + text: "PDF, JPG und PNG werden nicht öffentlich ausgeliefert, sondern nach Session und Kita geprüft.", + }, + { + title: "Lesestatus im Blick", + text: "Das System kann sichtbar machen, welche Ankündigungen für Nutzer noch ungelesen sind.", + }, + { + title: "Optional per E-Mail", + text: "Wichtige Meldungen können zusätzlich per E-Mail angestoßen werden.", + }, + ], + trustTitle: "Nicht öffentlich, nicht im Chat verloren", + trustText: + "Anhänge und Ankündigungen bleiben an Login, Rolle und Kita-Kontext gebunden. Das ist ruhiger und kontrollierter als öffentliche Links.", + faqs: [ + { + question: "Welche Dateitypen sind möglich?", + answer: + "Aktuell sind PDF, JPG und PNG vorgesehen.", + }, + { + question: "Sind Anhänge öffentlich erreichbar?", + answer: + "Nein. Anhänge werden nur nach Session- und Kita-Prüfung ausgeliefert.", + }, + { + question: "Kann eine Ankündigung per E-Mail versendet werden?", + answer: + "Ja. Für wichtige Meldungen ist optional ein E-Mail-Push vorgesehen.", + }, + ], + }, +]; + +export const marketingFeatureSlugs = marketingFeatures.map( + (feature) => feature.slug, +); + +export function getMarketingFeature(slug: string) { + return marketingFeatures.find((feature) => feature.slug === slug); +}