Update public feature details and align SEO metadata
This commit is contained in:
+103
-35
@@ -1,6 +1,7 @@
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import {
|
||||
CalendarDays,
|
||||
Clock3,
|
||||
Megaphone,
|
||||
ShieldAlert,
|
||||
Stethoscope,
|
||||
@@ -43,7 +44,7 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
title: "Fairer Notdienst-Planer",
|
||||
shortTitle: "Notdienst-Planer",
|
||||
description:
|
||||
"Automatische Generierung, gerechte Verteilung und 1-Klick-Alarmierung, wenn morgens Ersatz gebraucht wird.",
|
||||
"Verfügbarkeiten sammeln, Familien erinnern, Monatspläne veröffentlichen und bei Ausfällen Rückmeldungen erhalten.",
|
||||
accent: "bg-red-50 text-red-700 ring-red-100",
|
||||
eyebrow: "Notdienst ohne Excel-Lotterie",
|
||||
heroTitle: "Faire Notdienstplanung für Elterninitiativen.",
|
||||
@@ -57,11 +58,11 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
"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.",
|
||||
"Kita-Planer berücksichtigt Verfügbarkeiten und Mindesttage pro Kind, unterstützt die manuelle Einteilung und veröffentlicht den Monatsplan mit E-Mail-Benachrichtigung. Bei Ausfällen können Haushalte über persönliche Links zu- oder absagen.",
|
||||
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.",
|
||||
text: "Eltern hinterlegen mögliche Tage. Die Planung zählt Geschwister gemeinsam als Haushalt und zeigt, ob die erforderliche Auswahl vollständig ist.",
|
||||
},
|
||||
{
|
||||
title: "Nachvollziehbare Verteilung",
|
||||
@@ -69,11 +70,19 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
},
|
||||
{
|
||||
title: "Planung für Koordinatoren",
|
||||
text: "Koordinatoren sehen den Zielmonat, können Pläne erzeugen und bei Bedarf manuell nachsteuern.",
|
||||
text: "Koordinatoren erzeugen Planvorschläge und passen sie an. Verfügbare Haushalte stehen bei manuellen Einteilungen zuerst; abweichende Einteilungen werden gekennzeichnet.",
|
||||
},
|
||||
{
|
||||
title: "Schneller reagieren",
|
||||
text: "Wenn morgens Ersatz nötig ist, hilft eine strukturierte Übersicht deutlich mehr als ein hektischer Chat.",
|
||||
text: "Persönliche Alarmlinks ermöglichen Zu- oder Absagen. Verantwortliche behalten offene, bestätigte und verspätete Rückmeldungen im Blick.",
|
||||
},
|
||||
{
|
||||
title: "Erinnern und veröffentlichen",
|
||||
text: "Fehlende Verfügbarkeiten können per E-Mail erinnert werden. Mit der Veröffentlichung erhalten die eingeteilten Haushaltskonten ihre Termine.",
|
||||
},
|
||||
{
|
||||
title: "Dienste gemeinsam tauschen",
|
||||
text: "Eltern können einen Tausch anfragen. Eine bestätigte Anfrage tauscht die beiden Dienste; offene Anfragen bleiben sichtbar.",
|
||||
},
|
||||
],
|
||||
trustTitle: "Gemacht für sensible Kita-Abläufe",
|
||||
@@ -103,7 +112,7 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
title: "Smarter Kalender",
|
||||
shortTitle: "Kita-Kalender",
|
||||
description:
|
||||
"Feste, Termine, Raumbuchungen und digitale Mitbring-Listen in einem verbindlichen Kalender für alle Familien.",
|
||||
"Feste, Termine, Rückmeldungen und Mitbringlisten mit gemeinsamen Details in Monats-, Wochen-, Tages- und Agendaansicht.",
|
||||
accent: "bg-sky-50 text-sky-700 ring-sky-100",
|
||||
eyebrow: "Termine, Dienste und Mitbringlisten",
|
||||
heroTitle: "Ein Kita-Kalender, den Eltern wirklich nutzen.",
|
||||
@@ -111,7 +120,7 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
"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.",
|
||||
"Kita-Termine, Zusagen je Kind oder Haushalt und Mitbringlisten organisieren. Gemeinsame Details in Kalender und Agenda für Elterninitiativen.",
|
||||
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.",
|
||||
@@ -121,19 +130,19 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
benefits: [
|
||||
{
|
||||
title: "Termine im Überblick",
|
||||
text: "Feste, Schließtage, Elternabende und andere Ereignisse werden zentral sichtbar.",
|
||||
text: "Monats-, Wochen-, Tages- und Agendaansicht zeigen die gleichen Termindetails. Über die Suche lassen sich passende Ereignisse finden.",
|
||||
},
|
||||
{
|
||||
title: "Anfragen statt Nebenabsprachen",
|
||||
text: "Eltern können Terminwünsche einreichen, die von Verantwortlichen geprüft werden.",
|
||||
title: "Zusagen je Kind oder Haushalt",
|
||||
text: "Je nach Termin antworten Eltern für einzelne Kinder oder ihren Haushalt. Gemeinsam betreuende Eltern sehen denselben Antwortstand.",
|
||||
},
|
||||
{
|
||||
title: "Mitbringlisten direkt am Termin",
|
||||
text: "Was gebraucht wird, steht dort, wo Eltern es erwarten: am passenden Termin.",
|
||||
text: "Familien tragen ihren Beitrag direkt am Termin ein und können eigene Mitbring-Einträge ändern oder zurücknehmen.",
|
||||
},
|
||||
{
|
||||
title: "Dienste sichtbar machen",
|
||||
text: "Geplante Dienste werden im Kontext der kommenden Termine und Aufgaben angezeigt.",
|
||||
title: "Termine vorschlagen und prüfen",
|
||||
text: "Eltern reichen Terminanfragen ein. Berechtigte Personen prüfen sie; Dienste bleiben ebenfalls im Kalender sichtbar.",
|
||||
},
|
||||
],
|
||||
trustTitle: "Verbindlichkeit statt Chat-Suche",
|
||||
@@ -148,7 +157,7 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
{
|
||||
question: "Sind Mitbringlisten enthalten?",
|
||||
answer:
|
||||
"Ja. Termine können mit digitalen Mitbringlisten verbunden werden.",
|
||||
"Ja. Eltern können Beiträge eintragen und eigene Einträge bearbeiten oder zurücknehmen. Die Liste ist auch über die Agenda erreichbar.",
|
||||
},
|
||||
{
|
||||
question: "Wer sieht welche Termine?",
|
||||
@@ -163,7 +172,7 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
title: "Sicheres Adressbuch",
|
||||
shortTitle: "Eltern-Adressbuch",
|
||||
description:
|
||||
"Haushaltsbasiert, DSGVO-konform gedacht und mit strengem Opt-In: Kontaktdaten werden nur sichtbar, wenn Eltern zustimmen.",
|
||||
"Familien und Kinder gemeinsam finden. E-Mail, Telefon und Adresse eines Elternteils erscheinen nur nach dessen aktiver Freigabe.",
|
||||
accent: "bg-emerald-50 text-emerald-700 ring-emerald-100",
|
||||
eyebrow: "Kontakte nur mit Zustimmung",
|
||||
heroTitle: "Ein Eltern-Adressbuch mit klarer Freigabe.",
|
||||
@@ -202,8 +211,7 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
faqs: [
|
||||
{
|
||||
question: "Sind alle Eltern automatisch sichtbar?",
|
||||
answer:
|
||||
"Nein. Kontaktdaten erscheinen nur nach aktiver Freigabe.",
|
||||
answer: "Nein. Kontaktdaten erscheinen nur nach aktiver Freigabe.",
|
||||
},
|
||||
{
|
||||
question: "Kann eine Familie teilweise sichtbar sein?",
|
||||
@@ -253,8 +261,8 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
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.",
|
||||
title: "Künftige Meldungen korrigieren",
|
||||
text: "Eltern können Meldungen für zukünftige Tage selbst bearbeiten oder zurücknehmen. Laufende Meldungen verwaltet die Kita.",
|
||||
},
|
||||
],
|
||||
trustTitle: "Sensible Informationen geschützt behandeln",
|
||||
@@ -262,9 +270,9 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
"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?",
|
||||
question: "Können Eltern Meldungen später ändern?",
|
||||
answer:
|
||||
"Ja. Abwesenheiten können für einen Zeitraum erfasst werden.",
|
||||
"Ja, bei zukünftigen Tagen können Eltern eigene Meldungen bearbeiten oder zurücknehmen. Die Kita verwaltet laufende Meldungen.",
|
||||
},
|
||||
{
|
||||
question: "Sieht das Kita-Team die Meldungen sofort?",
|
||||
@@ -284,38 +292,38 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
title: "Schwarzes Brett",
|
||||
shortTitle: "Schwarzes Brett",
|
||||
description:
|
||||
"Offizielle Ankündigungen mit Dateianhängen, Lesebestätigung und optionalem E-Mail-Push statt verstreuter Chatposts.",
|
||||
"Ankündigungen mit geschützten Anhängen korrigieren, ältere Beiträge finden und den optionalen E-Mail-Versand je Person nachvollziehen.",
|
||||
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.",
|
||||
"Kita-Admins veröffentlichen Nachrichten für Eltern, Team oder beide Gruppen. Korrekturen erscheinen sichtbar aktualisiert und wieder ungelesen; ältere Beiträge bleiben auffindbar.",
|
||||
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.",
|
||||
"Kita-Mitteilungen mit Anhängen veröffentlichen und korrigieren. Ungelesene Beiträge erkennen, E-Mail-Status prüfen und Versandfehler erneut versuchen.",
|
||||
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.",
|
||||
"Nachrichten und Anhänge bleiben im geschützten Kita-Bereich. Admins können auch ältere Beiträge durchsuchen und korrigieren; der Versandstatus wird getrennt vom Inhalt verwaltet.",
|
||||
benefits: [
|
||||
{
|
||||
title: "Offizielle Ankündigungen",
|
||||
text: "Vorstände und Admins veröffentlichen zentrale Nachrichten an Eltern oder Team.",
|
||||
text: "Kita-Admins wählen Eltern, Team oder beide Gruppen. Diese Auswahl bestimmt auch, wer Beitrag und Anhänge in der App sehen darf.",
|
||||
},
|
||||
{
|
||||
title: "Geschützte Anhänge",
|
||||
text: "PDF, JPG und PNG werden nicht öffentlich ausgeliefert, sondern nach Session und Kita geprüft.",
|
||||
text: "PDF, JPG und PNG bleiben geschützt: bis zu fünf Dateien, je zehn MB und insgesamt 25 MB.",
|
||||
},
|
||||
{
|
||||
title: "Lesestatus im Blick",
|
||||
text: "Das System kann sichtbar machen, welche Ankündigungen für Nutzer noch ungelesen sind.",
|
||||
title: "Korrekturen bleiben sichtbar",
|
||||
text: "Geänderte Texte erhalten einen Aktualisierungszeitpunkt und erscheinen für Leser wieder ungelesen. Auch ältere Korrekturen rücken nach vorne.",
|
||||
},
|
||||
{
|
||||
title: "Optional per E-Mail",
|
||||
text: "Wichtige Meldungen können zusätzlich per E-Mail angestoßen werden.",
|
||||
title: "Versand je Person prüfen",
|
||||
text: "E-Mails sind optional. Erfolgreiche, ausstehende und fehlgeschlagene Sendungen werden getrennt angezeigt; Fehler können gezielt erneut versucht werden.",
|
||||
},
|
||||
],
|
||||
trustTitle: "Nicht öffentlich, nicht im Chat verloren",
|
||||
@@ -325,17 +333,77 @@ export const marketingFeatures: MarketingFeature[] = [
|
||||
{
|
||||
question: "Welche Dateitypen sind möglich?",
|
||||
answer:
|
||||
"Aktuell sind PDF, JPG und PNG vorgesehen.",
|
||||
"PDF, JPG und PNG sind möglich: bis zu fünf Anhänge, je zehn MB und insgesamt 25 MB.",
|
||||
},
|
||||
{
|
||||
question: "Sind Anhänge öffentlich erreichbar?",
|
||||
answer:
|
||||
"Nein. Anhänge werden nur nach Session- und Kita-Prüfung ausgeliefert.",
|
||||
"Nein. Anhänge sind nur nach Anmeldung und für die gewählte Empfängergruppe eurer Kita abrufbar.",
|
||||
},
|
||||
{
|
||||
question: "Kann eine Ankündigung per E-Mail versendet werden?",
|
||||
question: "Kann ich Fehler im Text oder beim Mailversand korrigieren?",
|
||||
answer:
|
||||
"Ja. Für wichtige Meldungen ist optional ein E-Mail-Push vorgesehen.",
|
||||
"Ja. Admins können Titel und Text bearbeiten und die aktuelle Fassung ausdrücklich per E-Mail senden. Fehlgeschlagene Sendungen lassen sich unabhängig davon erneut versuchen; bereits erfolgreiche E-Mails werden dabei ausgelassen.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: "personal-arbeitszeit",
|
||||
icon: Clock3,
|
||||
title: "Personal & Arbeitszeit",
|
||||
shortTitle: "Personal und Arbeitszeit",
|
||||
description:
|
||||
"Arbeitszeit mit Pausen erfassen, Wochen zur Freigabe einreichen und Urlaub, Freizeitausgleich sowie das bestätigte Zeitkonto im Blick behalten.",
|
||||
accent: "bg-teal-50 text-teal-700 ring-teal-100",
|
||||
eyebrow: "Arbeitszeit, Urlaub und Zeitkonto",
|
||||
heroTitle: "Mehr Überblick über die Arbeitszeit im Kita-Team.",
|
||||
heroDescription:
|
||||
"Fachkräfte erfassen ihre Arbeitsblöcke und stellen Anträge. Kita-Admins prüfen Wochen, genehmigen Urlaub und führen nachvollziehbare Zeitkonten.",
|
||||
seoTitle: "Arbeitszeit und Urlaub für Kita-Teams",
|
||||
seoDescription:
|
||||
"Kita-Arbeitszeit mit Pausen erfassen, Wochen freigeben und Urlaub oder Freizeitausgleich beantragen. Zeitkonto und Resturlaub nachvollziehbar verwalten.",
|
||||
problemTitle: "Arbeitszeit und Urlaub landen oft in mehreren Listen",
|
||||
problemText:
|
||||
"Einzelne Stundenlisten, Urlaubsanfragen und manuell berechnete Salden machen es schwer, einen gemeinsamen und bestätigten Stand zu behalten.",
|
||||
solutionTitle: "Erfassung, Antrag und Freigabe gemeinsam organisieren",
|
||||
solutionText:
|
||||
"Arbeitsblöcke und Pausen gehören zur jeweiligen Woche. Anträge und Freigaben bleiben mit dem Personalprofil verknüpft; bestätigte Wochen und begründete Korrekturen führen zum Zeitkonto.",
|
||||
benefits: [
|
||||
{
|
||||
title: "Mehrere Arbeitsblöcke je Tag",
|
||||
text: "Fachkräfte erfassen Beginn, Ende und Pause. Weitere Blöcke lassen sich für denselben ausgewählten Tag direkt ergänzen.",
|
||||
},
|
||||
{
|
||||
title: "Wochen prüfen und freigeben",
|
||||
text: "Fachkräfte reichen die Woche ein. Admins können sie prüfen, freigeben oder zur Korrektur zurückgeben.",
|
||||
},
|
||||
{
|
||||
title: "Urlaub und Freizeitausgleich",
|
||||
text: "Ganze und einzelne halbe Urlaubstage sowie Freizeitausgleich können beantragt werden. Nur vorgesehene Arbeitstage verbrauchen Urlaub.",
|
||||
},
|
||||
{
|
||||
title: "Bestätigtes Zeitkonto",
|
||||
text: "Genehmigte Wochen, Anfangssaldo und wirksame manuelle Korrekturen bilden das bestätigte Konto. Offene Wochen bleiben als vorläufig erkennbar.",
|
||||
},
|
||||
],
|
||||
trustTitle: "Persönliche Zeiten mit klaren Zuständigkeiten",
|
||||
trustText:
|
||||
"Fachkräfte sehen ihr eigenes Profil und ihre Zeiten. Kita-Admins verwalten die Personalprofile ihrer Einrichtung; Zugriffsrechte und bestehende Profile bleiben miteinander verbunden.",
|
||||
faqs: [
|
||||
{
|
||||
question: "Sind mehrere Arbeitsblöcke am selben Tag möglich?",
|
||||
answer:
|
||||
"Ja. Zum Beispiel lassen sich ein Vormittags- und ein Nachmittagsblock getrennt erfassen, jeweils mit passender Pause.",
|
||||
},
|
||||
{
|
||||
question: "Kann ich einen halben Urlaubstag beantragen?",
|
||||
answer:
|
||||
"Ja. Ein halber Urlaubstag bezieht sich auf ein einzelnes Datum. Auch für Freizeitausgleich wird ein Tag ausgewählt.",
|
||||
},
|
||||
{
|
||||
question: "Zählt eine offene Woche bereits zum bestätigten Zeitkonto?",
|
||||
answer:
|
||||
"Nein. Erst genehmigte Wochen zählen zusammen mit Anfangssaldo und wirksamen Korrekturen zum bestätigten Konto.",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
// Update when the public product copy changes, never on each request or build.
|
||||
export const marketingLastModified = "2026-10-13";
|
||||
export const marketingTitle =
|
||||
"Kita-Planer für Elterninitiativen und Kita-Vereine";
|
||||
export const marketingDescription =
|
||||
"Organisiert Notdienste, Termine, Abwesenheiten, Arbeitszeit und Kita-Mitteilungen mit klaren Rollen, geschützten Anhängen und optionalen E-Mails.";
|
||||
export const socialImage = {
|
||||
url: "/og-image.png",
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: "Bunte Spielklötze mit Tiermotiven für den Kita-Alltag.",
|
||||
};
|
||||
|
||||
export function getPublicSiteOrigin() {
|
||||
const site = new URL(
|
||||
process.env.NEXT_PUBLIC_SITE_URL?.trim() || "https://mein-kitaplaner.de",
|
||||
);
|
||||
if (
|
||||
!["https:", "http:"].includes(site.protocol) ||
|
||||
site.username ||
|
||||
site.password
|
||||
)
|
||||
throw new Error(
|
||||
"NEXT_PUBLIC_SITE_URL muss eine öffentliche HTTP(S)-Adresse ohne Zugangsdaten sein.",
|
||||
);
|
||||
return site.origin;
|
||||
}
|
||||
|
||||
export function publicUrl(path = "/") {
|
||||
if (!path.startsWith("/") || path.startsWith("//"))
|
||||
throw new Error("Ungültiger öffentlicher Seitenpfad.");
|
||||
const origin = getPublicSiteOrigin();
|
||||
const url = new URL(path, origin);
|
||||
if (url.origin !== origin)
|
||||
throw new Error("Ungültiger öffentlicher Seitenpfad.");
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
export function publicPageMetadata(
|
||||
path: string,
|
||||
title: string,
|
||||
description: string,
|
||||
): Metadata {
|
||||
return {
|
||||
title: {
|
||||
absolute: title.includes("Kita-Planer")
|
||||
? title
|
||||
: `${title} | Kita-Planer`,
|
||||
},
|
||||
description,
|
||||
alternates: { canonical: publicUrl(path) },
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
googleBot: { index: true, follow: true, "max-image-preview": "large" },
|
||||
},
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
url: publicUrl(path),
|
||||
siteName: "Kita-Planer",
|
||||
type: "website",
|
||||
locale: "de_DE",
|
||||
images: [socialImage],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title,
|
||||
description,
|
||||
images: [{ url: socialImage.url, alt: socialImage.alt }],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function websiteStructuredData() {
|
||||
return {
|
||||
"@type": "WebSite",
|
||||
"@id": publicUrl("/#website"),
|
||||
name: "Kita-Planer",
|
||||
url: publicUrl(),
|
||||
inLanguage: "de-DE",
|
||||
};
|
||||
}
|
||||
|
||||
export function landingStructuredData(
|
||||
features: { title: string; description: string }[],
|
||||
) {
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
websiteStructuredData(),
|
||||
{
|
||||
"@type": "WebPage",
|
||||
"@id": publicUrl("/#webpage"),
|
||||
url: publicUrl(),
|
||||
name: marketingTitle,
|
||||
description: marketingDescription,
|
||||
inLanguage: "de-DE",
|
||||
isPartOf: { "@id": publicUrl("/#website") },
|
||||
about: { "@id": publicUrl("/#software") },
|
||||
},
|
||||
{
|
||||
"@type": "SoftwareApplication",
|
||||
"@id": publicUrl("/#software"),
|
||||
name: "Kita-Planer",
|
||||
url: publicUrl(),
|
||||
description: marketingDescription,
|
||||
applicationCategory: "BusinessApplication",
|
||||
operatingSystem: "Webbrowser",
|
||||
inLanguage: "de-DE",
|
||||
featureList: features.map(
|
||||
(feature) => `${feature.title}: ${feature.description}`,
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function featureStructuredData(feature: {
|
||||
slug: string;
|
||||
shortTitle: string;
|
||||
seoTitle: string;
|
||||
seoDescription: string;
|
||||
}) {
|
||||
const path = `/features/${feature.slug}`;
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
websiteStructuredData(),
|
||||
{
|
||||
"@type": "WebPage",
|
||||
"@id": publicUrl(`${path}#webpage`),
|
||||
url: publicUrl(path),
|
||||
name: feature.seoTitle,
|
||||
description: feature.seoDescription,
|
||||
inLanguage: "de-DE",
|
||||
isPartOf: { "@id": publicUrl("/#website") },
|
||||
breadcrumb: { "@id": publicUrl(`${path}#breadcrumb`) },
|
||||
},
|
||||
{
|
||||
"@type": "BreadcrumbList",
|
||||
"@id": publicUrl(`${path}#breadcrumb`),
|
||||
itemListElement: [
|
||||
{
|
||||
"@type": "ListItem",
|
||||
position: 1,
|
||||
name: "Kita-Planer",
|
||||
item: publicUrl(),
|
||||
},
|
||||
{
|
||||
"@type": "ListItem",
|
||||
position: 2,
|
||||
name: feature.shortTitle,
|
||||
item: publicUrl(path),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function serializeStructuredData(data: unknown) {
|
||||
return JSON.stringify(data).replace(/</g, "\\u003c");
|
||||
}
|
||||
Reference in New Issue
Block a user