This commit is contained in:
2026-07-10 21:52:36 +02:00
parent bb528d6ef9
commit 671c1a1559
28 changed files with 6396 additions and 5561 deletions

110
src/app/de/[slug]/page.tsx Normal file
View File

@@ -0,0 +1,110 @@
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { UseCasePageTemplate } from '@/components/marketing/UseCasePageTemplate';
import {
getUseCasePageDe,
useCasePagesDe,
useCaseTemplateLabelsDe,
} from '@/lib/growth-pages-de';
import { buildLanguageAlternates, absoluteUrl } from '@/lib/i18n';
export const dynamicParams = false;
export function generateStaticParams() {
return Object.keys(useCasePagesDe).map((slug) => ({ slug }));
}
export function generateMetadata({ params }: { params: { slug: string } }): Metadata {
const page = getUseCasePageDe(params.slug);
if (!page) {
return {};
}
const alternates = buildLanguageAlternates({
en: `/use-cases/${page.enSlug}`,
de: page.href,
});
return {
title: {
absolute: `${page.title} | QR Master`,
},
description: page.metaDescription,
alternates: {
// The German page canonicalizes to itself; hreflang links the pair.
canonical: absoluteUrl(page.href),
languages: alternates.languages,
},
openGraph: {
title: `${page.title} | QR Master`,
description: page.metaDescription,
url: absoluteUrl(page.href),
type: 'website',
locale: 'de_DE',
images: ['/og-image.png'],
},
twitter: {
title: `${page.title} | QR Master`,
description: page.metaDescription,
},
};
}
export default function UseCaseDetailPageDe({
params,
}: {
params: { slug: string };
}) {
const page = getUseCasePageDe(params.slug);
if (!page) {
notFound();
}
return (
<UseCasePageTemplate
title={page.title}
description={page.metaDescription}
eyebrow={page.eyebrow}
intro={page.intro}
pageType="use_case"
cluster={page.cluster}
useCase={page.slug}
breadcrumbs={[
{ name: 'Startseite', url: '/qr-code-erstellen' },
{ name: page.title, url: page.href },
]}
answer={page.answer}
whenToUse={page.whenToUse}
comparisonItems={page.comparisonItems}
howToSteps={page.howToSteps}
primaryCta={{
// German visitors should convert on the German generator page, not
// the English commercial parent.
href: '/qr-code-erstellen',
label: page.ctaLabel,
}}
secondaryCta={{
href: page.parentHref,
label: `Mehr erfahren: ${page.parentTitle}`,
}}
workflowTitle={page.workflowTitle}
workflowIntro={page.workflowIntro}
workflowCards={page.workflowCards}
checklistTitle={page.checklistTitle}
checklist={page.checklist}
supportLinks={page.supportLinks}
faq={page.faq}
heroImage={page.heroImage}
heroImageAlt={page.heroImageAlt}
authoritySignals={page.authoritySignals}
directAnswer={page.directAnswer}
labels={{
...useCaseTemplateLabelsDe,
faqTitle: `FAQ: ${page.title}`,
}}
/>
);
}

79
src/app/de/layout.tsx Normal file
View File

@@ -0,0 +1,79 @@
import type { Metadata } from 'next';
import { Suspense } from 'react';
import '@/styles/globals.css';
import { Providers } from '@/components/Providers';
import MarketingDeLayout from '@/components/marketing/MarketingDeLayout';
import { organizationSchema, websiteSchema } from '@/lib/schema';
import FacebookPixel from '@/components/analytics/FacebookPixel';
export const metadata: Metadata = {
title: {
default: 'QR Master QR Code Generator & Analytics',
template: '%s | QR Master',
},
description: 'Erstellen Sie dynamische QR Codes für Feedback, PDF, Coupons und App Stores. Verfolgen Sie Scans und skalieren Sie Kampagnen mit sicheren Analysen.',
metadataBase: new URL('https://www.qrmaster.net'),
icons: {
icon: [
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/favicon.ico', sizes: '16x16 32x32', type: 'image/x-icon' },
],
shortcut: '/favicon.ico',
apple: '/logo.svg',
},
openGraph: {
type: 'website',
siteName: 'QR Master',
title: 'QR Master QR Code Generator & Analytics',
description: 'Erstellen Sie dynamische QR Codes für Feedback, PDF, Coupons und App Stores. Verfolgen Sie Scans und skalieren Sie Kampagnen mit sicheren Analysen.',
locale: 'de_DE',
images: [
{
url: 'https://www.qrmaster.net/og-image.png',
width: 1200,
height: 630,
alt: 'QR Master - Dynamischer QR Code Generator',
},
],
},
twitter: {
card: 'summary_large_image',
site: '@qrmaster',
images: ['https://www.qrmaster.net/og-image.png'],
},
robots: { index: true, follow: true },
verification: {
other: {
'facebook-domain-verification': process.env.NEXT_PUBLIC_FACEBOOK_DOMAIN_VERIFICATION || '',
},
},
};
export default function GermanRootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="de">
<body className="font-sans">
<Suspense fallback={null}>
<Providers>
<FacebookPixel />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema()) }}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(websiteSchema()) }}
/>
<MarketingDeLayout>
{children}
</MarketingDeLayout>
</Providers>
</Suspense>
</body>
</html>
);
}

View File

@@ -0,0 +1,85 @@
import React from 'react';
import type { Metadata } from 'next';
import SeoJsonLd from '@/components/SeoJsonLd';
import { Pricing } from '@/components/marketing/Pricing';
import { FAQSection } from '@/components/aeo/FAQSection';
import { breadcrumbSchema, faqPageSchema } from '@/lib/schema';
import { getDictionary, buildLanguageAlternates, absoluteUrl } from '@/lib/i18n';
const alternates = buildLanguageAlternates({ en: '/pricing', de: '/de/preise' });
export const metadata: Metadata = {
title: {
absolute: 'Preise & Pläne | QR Master',
},
description:
'QR Master Preise im Vergleich: Free mit 3 aktiven dynamischen QR-Codes, Pro mit 50 und Business mit 500 inklusive Massen-Erstellung.',
alternates: {
canonical: absoluteUrl('/de/preise'),
languages: alternates.languages,
},
robots: {
index: true,
follow: true,
},
openGraph: {
title: 'Preise & Pläne | QR Master',
description:
'QR Master Preise im Vergleich: Free mit 3 aktiven dynamischen QR-Codes, Pro mit 50 und Business mit 500 inklusive Massen-Erstellung.',
url: absoluteUrl('/de/preise'),
type: 'website',
locale: 'de_DE',
images: [
{
url: 'https://www.qrmaster.net/og-image.png',
width: 1200,
height: 630,
alt: 'QR Master Preise & Pläne',
},
],
},
};
const faqItems = [
{
question: 'Wie viele dynamische QR-Codes sind in den einzelnen Plänen enthalten?',
answer:
'Free enthält 3 aktive dynamische QR-Codes. Pro enthält 50 dynamische QR-Codes. Business enthält 500 dynamische QR-Codes.',
},
{
question: 'Enthalten alle Pläne statische QR-Codes?',
answer: 'Ja. Alle Pläne enthalten unbegrenzt viele statische QR-Codes.',
},
{
question: 'Welcher Plan enthält die Massen-Erstellung (Bulk)?',
answer: 'Die Massen-Erstellung von QR-Codes ist im Business-Plan enthalten.',
},
{
question: 'Welche Pläne enthalten Statistiken und Branding?',
answer:
'Der Free-Plan enthält grundlegendes Scan-Tracking. Pro ergänzt erweiterte Statistiken und individuelles Branding. Business enthält alles aus Pro plus Massen-Erstellung und Prioritäts-Support per E-Mail.',
},
];
const breadcrumbItems = [
{ name: 'Startseite', url: '/qr-code-erstellen' },
{ name: 'Preise', url: '/de/preise' },
];
export default function PreisePage() {
const t = getDictionary('de');
return (
<>
<SeoJsonLd data={[breadcrumbSchema(breadcrumbItems), faqPageSchema(faqItems)]} />
<div className="bg-white">
<Pricing t={t} />
<div className="container mx-auto max-w-5xl px-4 py-10 sm:px-6 lg:px-8">
<FAQSection items={faqItems} title="Fragen zu den Preisen" />
</div>
</div>
</>
);
}