SEO V2
This commit is contained in:
@@ -5,10 +5,9 @@ import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Footer } from '@/components/ui/Footer';
|
||||
import en from '@/i18n/en.json';
|
||||
import { allUseCases } from '@/lib/growth-pages';
|
||||
import { LayoutGrid } from 'lucide-react';
|
||||
import { ChevronDown, BookOpen, Building2, Wifi, Contact, MessageCircle, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon, Star } from 'lucide-react';
|
||||
import en from '@/i18n/en.json';
|
||||
import { publishedUseCases } from '@/lib/growth-pages';
|
||||
import { ChevronDown, LayoutGrid, BookOpen, Building2, Wifi, Contact, MessageCircle, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon, Star } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import Image from 'next/image';
|
||||
@@ -20,10 +19,10 @@ export default function MarketingLayout({
|
||||
}) {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const [toolsOpen, setToolsOpen] = useState(false);
|
||||
const [toolsOpen, setToolsOpen] = useState(false);
|
||||
const [useCasesOpen, setUseCasesOpen] = useState(false);
|
||||
const [resourcesOpen, setResourcesOpen] = useState(false);
|
||||
const [mobileToolsOpen, setMobileToolsOpen] = useState(false);
|
||||
const [mobileToolsOpen, setMobileToolsOpen] = useState(false);
|
||||
const [mobileUseCasesOpen, setMobileUseCasesOpen] = useState(false);
|
||||
const [mobileResourcesOpen, setMobileResourcesOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
@@ -40,10 +39,10 @@ export default function MarketingLayout({
|
||||
// Close simple menus when path changes
|
||||
useEffect(() => {
|
||||
setMobileMenuOpen(false);
|
||||
setToolsOpen(false);
|
||||
setToolsOpen(false);
|
||||
setUseCasesOpen(false);
|
||||
setResourcesOpen(false);
|
||||
setMobileToolsOpen(false);
|
||||
setMobileToolsOpen(false);
|
||||
setMobileUseCasesOpen(false);
|
||||
setMobileResourcesOpen(false);
|
||||
}, [pathname]);
|
||||
@@ -151,50 +150,50 @@ export default function MarketingLayout({
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Use Cases Dropdown */}
|
||||
<div
|
||||
className="relative group px-3 py-2"
|
||||
onMouseEnter={() => setUseCasesOpen(true)}
|
||||
onMouseLeave={() => setUseCasesOpen(false)}
|
||||
>
|
||||
<button className="flex items-center space-x-1 text-sm font-medium text-slate-600 group-hover:text-slate-900 transition-colors">
|
||||
<span>Use Cases</span>
|
||||
<ChevronDown className={cn("w-4 h-4 transition-transform duration-200", useCasesOpen && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{useCasesOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 10 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
className="absolute left-1/2 -translate-x-1/2 top-full mt-2 w-[700px] bg-white rounded-2xl shadow-lg border border-slate-100 p-4 overflow-hidden"
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{allUseCases.map((uc) => (
|
||||
<Link
|
||||
key={uc.slug}
|
||||
href={uc.href}
|
||||
className="flex items-center space-x-3 p-2.5 rounded-xl transition-colors hover:bg-slate-50"
|
||||
>
|
||||
<div className="p-2 rounded-lg shrink-0 bg-indigo-50 text-indigo-500">
|
||||
<LayoutGrid className="w-4 h-4" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-semibold text-slate-900">{uc.title}</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-3 pt-3 border-t border-slate-100 -mx-4 -mb-4 px-4 py-3 text-center bg-slate-50/50">
|
||||
<Link href="/use-cases" className="text-xs text-indigo-600 font-medium hover:underline">View All Use Cases →</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Use Cases Dropdown */}
|
||||
<div
|
||||
className="relative group px-3 py-2"
|
||||
onMouseEnter={() => setUseCasesOpen(true)}
|
||||
onMouseLeave={() => setUseCasesOpen(false)}
|
||||
>
|
||||
<button className="flex items-center space-x-1 text-sm font-medium text-slate-600 group-hover:text-slate-900 transition-colors">
|
||||
<span>Use Cases</span>
|
||||
<ChevronDown className={cn("w-4 h-4 transition-transform duration-200", useCasesOpen && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{useCasesOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 10 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
className="absolute left-1/2 -translate-x-1/2 top-full mt-2 w-[700px] bg-white rounded-2xl shadow-lg border border-slate-100 p-4 overflow-hidden"
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{publishedUseCases.map((uc) => (
|
||||
<Link
|
||||
key={uc.slug}
|
||||
href={uc.href}
|
||||
className="flex items-center space-x-3 p-2.5 rounded-xl transition-colors hover:bg-slate-50"
|
||||
>
|
||||
<div className="p-2 rounded-lg shrink-0 bg-indigo-50 text-indigo-500">
|
||||
<LayoutGrid className="w-4 h-4" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-semibold text-slate-900">{uc.title}</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-3 pt-3 border-t border-slate-100 -mx-4 -mb-4 px-4 py-3 text-center bg-slate-50/50">
|
||||
<Link href="/use-cases" className="text-xs text-indigo-600 font-medium hover:underline">View All Use Cases →</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Tools Dropdown */}
|
||||
<div
|
||||
className="relative group px-3 py-2"
|
||||
@@ -329,39 +328,39 @@ export default function MarketingLayout({
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Use Cases Accordion */}
|
||||
<button
|
||||
onClick={() => setMobileUseCasesOpen(!mobileUseCasesOpen)}
|
||||
className="flex items-center justify-between w-full px-4 py-3 rounded-xl hover:bg-slate-50 text-slate-700 font-semibold"
|
||||
>
|
||||
<span>Use Cases</span>
|
||||
<ChevronDown className={cn("w-5 h-5 transition-transform", mobileUseCasesOpen && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{mobileUseCasesOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<div className="max-h-[50vh] overflow-y-auto pl-4 space-y-1 border-l-2 border-slate-100 ml-4">
|
||||
{allUseCases.map((uc) => (
|
||||
<Link
|
||||
key={uc.slug}
|
||||
href={uc.href}
|
||||
className="block px-4 py-2.5 rounded-lg hover:bg-slate-50 text-slate-600 text-sm"
|
||||
onClick={() => { setMobileMenuOpen(false); setMobileUseCasesOpen(false); }}
|
||||
>
|
||||
{uc.title}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Use Cases Accordion */}
|
||||
<button
|
||||
onClick={() => setMobileUseCasesOpen(!mobileUseCasesOpen)}
|
||||
className="flex items-center justify-between w-full px-4 py-3 rounded-xl hover:bg-slate-50 text-slate-700 font-semibold"
|
||||
>
|
||||
<span>Use Cases</span>
|
||||
<ChevronDown className={cn("w-5 h-5 transition-transform", mobileUseCasesOpen && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{mobileUseCasesOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<div className="max-h-[50vh] overflow-y-auto pl-4 space-y-1 border-l-2 border-slate-100 ml-4">
|
||||
{publishedUseCases.map((uc) => (
|
||||
<Link
|
||||
key={uc.slug}
|
||||
href={uc.href}
|
||||
className="block px-4 py-2.5 rounded-lg hover:bg-slate-50 text-slate-600 text-sm"
|
||||
onClick={() => { setMobileMenuOpen(false); setMobileUseCasesOpen(false); }}
|
||||
>
|
||||
{uc.title}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Free Tools Accordion */}
|
||||
<button
|
||||
onClick={() => setMobileToolsOpen(!mobileToolsOpen)}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import PricingClient from './PricingClient';
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import PricingClient from './PricingClient';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { AnswerFirstBlock } from '@/components/marketing/AnswerFirstBlock';
|
||||
import { FAQSection } from '@/components/aeo/FAQSection';
|
||||
@@ -15,6 +15,11 @@ export const metadata: Metadata = {
|
||||
'Compare QR Master pricing plans. Free includes 3 active dynamic QR codes, Pro includes 50, and Business includes 500 plus bulk QR creation.',
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/pricing',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/pricing',
|
||||
en: 'https://www.qrmaster.net/pricing',
|
||||
de: 'https://www.qrmaster.net/de/preise',
|
||||
},
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
@@ -98,30 +103,30 @@ export default function PricingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto max-w-5xl px-4 pb-4 sm:px-6 lg:px-8">
|
||||
<FAQSection items={faqItems} title="Pricing questions" />
|
||||
</div>
|
||||
|
||||
<section className="container mx-auto max-w-5xl px-4 pb-10 sm:px-6 lg:px-8">
|
||||
<div className="rounded-lg border border-slate-200 bg-slate-50 p-5">
|
||||
<h2 className="text-xl font-semibold text-slate-900">
|
||||
Not sure whether free is enough?
|
||||
</h2>
|
||||
<p className="mt-3 max-w-3xl leading-7 text-slate-600">
|
||||
Compare free QR generators with paid dynamic QR workflows before
|
||||
choosing a plan. The difference usually comes down to editing
|
||||
after print, scan tracking, branding, and reprint risk.
|
||||
</p>
|
||||
<Link
|
||||
href="/compare/free-vs-paid-qr-code-generator"
|
||||
className="mt-4 inline-flex text-sm font-semibold text-blue-700 hover:text-blue-800"
|
||||
>
|
||||
Read the free vs paid QR generator comparison
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="sr-only">
|
||||
<div className="container mx-auto max-w-5xl px-4 pb-4 sm:px-6 lg:px-8">
|
||||
<FAQSection items={faqItems} title="Pricing questions" />
|
||||
</div>
|
||||
|
||||
<section className="container mx-auto max-w-5xl px-4 pb-10 sm:px-6 lg:px-8">
|
||||
<div className="rounded-lg border border-slate-200 bg-slate-50 p-5">
|
||||
<h2 className="text-xl font-semibold text-slate-900">
|
||||
Not sure whether free is enough?
|
||||
</h2>
|
||||
<p className="mt-3 max-w-3xl leading-7 text-slate-600">
|
||||
Compare free QR generators with paid dynamic QR workflows before
|
||||
choosing a plan. The difference usually comes down to editing
|
||||
after print, scan tracking, branding, and reprint risk.
|
||||
</p>
|
||||
<Link
|
||||
href="/compare/free-vs-paid-qr-code-generator"
|
||||
className="mt-4 inline-flex text-sm font-semibold text-blue-700 hover:text-blue-800"
|
||||
>
|
||||
Read the free vs paid QR generator comparison
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="sr-only">
|
||||
<h2>Compare our plans</h2>
|
||||
<p>
|
||||
Free includes 3 active dynamic QR codes and unlimited static QR codes. Pro
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
UseCasePageTemplate,
|
||||
} from '@/components/marketing/UseCasePageTemplate';
|
||||
import { allUseCases, getUseCasePage } from '@/lib/growth-pages';
|
||||
import { getGermanTwinByEnSlug } from '@/lib/growth-pages-de';
|
||||
|
||||
export function generateStaticParams() {
|
||||
return allUseCases.map((item) => ({
|
||||
@@ -23,6 +24,7 @@ export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
title: page.title,
|
||||
description: page.metaDescription,
|
||||
canonicalPath: page.href,
|
||||
dePath: getGermanTwinByEnSlug(page.slug)?.href,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ import {
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import {
|
||||
allUseCases,
|
||||
commercialPages,
|
||||
featuredUseCases,
|
||||
publishedUseCases,
|
||||
supportResources,
|
||||
upcomingUseCaseIdeas,
|
||||
} from "@/lib/growth-pages";
|
||||
@@ -184,7 +184,7 @@ export default function UseCasesHubPage() {
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
|
||||
{allUseCases.map((page) => (
|
||||
{publishedUseCases.map((page) => (
|
||||
<Link key={page.slug} href={page.href} className="group block">
|
||||
<Card className="flex h-full flex-col rounded-3xl border-slate-200 bg-white p-7 shadow-sm transition-all hover:-translate-y-1 hover:shadow-lg">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.18em] text-blue-700">
|
||||
@@ -205,66 +205,66 @@ export default function UseCasesHubPage() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-8 max-w-3xl">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.22em] text-blue-700">
|
||||
Industry pages with early traction
|
||||
</div>
|
||||
<h2 className="mt-3 text-3xl font-bold text-slate-900">
|
||||
Service business QR workflows
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-8 text-slate-600">
|
||||
These industry routes connect practical use cases with the QR
|
||||
tools local businesses usually need first.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
href: "/qr-code-for/barbershops",
|
||||
title: "QR Codes for Barbershops",
|
||||
description:
|
||||
"Booking links, review prompts, WiFi access, and social profiles for barbershop visits.",
|
||||
},
|
||||
{
|
||||
href: "/tools/wifi-qr-code",
|
||||
title: "WiFi QR Code Generator",
|
||||
description:
|
||||
"A practical guest-facing QR tool for service businesses and venues.",
|
||||
},
|
||||
{
|
||||
href: "/qr-code-erstellen",
|
||||
title: "QR Code Erstellen",
|
||||
description:
|
||||
"German QR creation page for local business owners who search in German.",
|
||||
},
|
||||
].map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="rounded-2xl border border-slate-200 bg-slate-50 p-6 transition-colors hover:border-blue-200 hover:bg-blue-50/70"
|
||||
>
|
||||
<h3 className="text-xl font-bold text-slate-900">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-6 text-slate-600">
|
||||
{item.description}
|
||||
</p>
|
||||
<div className="mt-5 inline-flex items-center text-sm font-semibold text-blue-700">
|
||||
Open page <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-slate-50 py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
</section>
|
||||
|
||||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-8 max-w-3xl">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.22em] text-blue-700">
|
||||
Industry pages with early traction
|
||||
</div>
|
||||
<h2 className="mt-3 text-3xl font-bold text-slate-900">
|
||||
Service business QR workflows
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-8 text-slate-600">
|
||||
These industry routes connect practical use cases with the QR
|
||||
tools local businesses usually need first.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
href: "/qr-code-for/barbershops",
|
||||
title: "QR Codes for Barbershops",
|
||||
description:
|
||||
"Booking links, review prompts, WiFi access, and social profiles for barbershop visits.",
|
||||
},
|
||||
{
|
||||
href: "/tools/wifi-qr-code",
|
||||
title: "WiFi QR Code Generator",
|
||||
description:
|
||||
"A practical guest-facing QR tool for service businesses and venues.",
|
||||
},
|
||||
{
|
||||
href: "/qr-code-erstellen",
|
||||
title: "QR Code Erstellen",
|
||||
description:
|
||||
"German QR creation page for local business owners who search in German.",
|
||||
},
|
||||
].map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="rounded-2xl border border-slate-200 bg-slate-50 p-6 transition-colors hover:border-blue-200 hover:bg-blue-50/70"
|
||||
>
|
||||
<h3 className="text-xl font-bold text-slate-900">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-6 text-slate-600">
|
||||
{item.description}
|
||||
</p>
|
||||
<div className="mt-5 inline-flex items-center text-sm font-semibold text-blue-700">
|
||||
Open page <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-slate-50 py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(0,0.95fr)]">
|
||||
<Card className="rounded-3xl border-slate-200 bg-white p-8 shadow-sm">
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Footer } from '@/components/ui/Footer';
|
||||
import de from '@/i18n/de.json';
|
||||
import { ChevronDown, Wifi, Contact, MessageCircle, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function MarketingLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const [toolsOpen, setToolsOpen] = useState(false);
|
||||
const [mobileToolsOpen, setMobileToolsOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setScrolled(window.scrollY > 20);
|
||||
};
|
||||
|
||||
// Check immediately on mount
|
||||
handleScroll();
|
||||
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
// Close simple menus when path changes
|
||||
useEffect(() => {
|
||||
setMobileMenuOpen(false);
|
||||
setToolsOpen(false);
|
||||
}, [pathname]);
|
||||
|
||||
// Always German for this layout
|
||||
const t = de;
|
||||
|
||||
const tools = [
|
||||
{ name: 'URL / Link', description: 'Link to any website', href: '/tools/url-qr-code', icon: Link2, color: 'text-blue-500', bgColor: 'bg-blue-50' },
|
||||
{ name: 'Text', description: 'Plain text message', href: '/tools/text-qr-code', icon: Type, color: 'text-slate-500', bgColor: 'bg-slate-50' },
|
||||
{ name: 'WiFi', description: 'Share WiFi credentials', href: '/tools/wifi-qr-code', icon: Wifi, color: 'text-indigo-500', bgColor: 'bg-indigo-50' },
|
||||
{ name: 'VCard', description: 'Digital business card', href: '/tools/vcard-qr-code', icon: Contact, color: 'text-pink-500', bgColor: 'bg-pink-50' },
|
||||
{ name: 'WhatsApp', description: 'Start a chat', href: '/tools/whatsapp-qr-code', icon: MessageCircle, color: 'text-green-500', bgColor: 'bg-green-50' },
|
||||
{ name: 'Email', description: 'Compose an email', href: '/tools/email-qr-code', icon: Mail, color: 'text-amber-500', bgColor: 'bg-amber-50' },
|
||||
{ name: 'SMS', description: 'Send a text message', href: '/tools/sms-qr-code', icon: MessageSquare, color: 'text-cyan-500', bgColor: 'bg-cyan-50' },
|
||||
{ name: 'Call', description: 'Anruf starten', href: '/tools/call-qr-code-generator', icon: Phone, color: 'text-violet-500', bgColor: 'bg-violet-50' },
|
||||
{ name: 'Event', description: 'Add calendar event', href: '/tools/event-qr-code', icon: Calendar, color: 'text-red-500', bgColor: 'bg-red-50' },
|
||||
{ name: 'Location', description: 'Share a place', href: '/tools/geolocation-qr-code', icon: MapPin, color: 'text-emerald-500', bgColor: 'bg-emerald-50' },
|
||||
{ name: 'Facebook', description: 'Facebook profile/page', href: '/tools/facebook-qr-code', icon: Facebook, color: 'text-blue-600', bgColor: 'bg-blue-50' },
|
||||
{ name: 'Instagram', description: 'Instagram profile', href: '/tools/instagram-qr-code', icon: Instagram, color: 'text-pink-600', bgColor: 'bg-pink-50' },
|
||||
{ name: 'Twitter / X', description: 'Twitter profile', href: '/tools/twitter-qr-code', icon: Twitter, color: 'text-sky-500', bgColor: 'bg-sky-50' },
|
||||
{ name: 'YouTube', description: 'YouTube video/channel', href: '/tools/youtube-qr-code', icon: Youtube, color: 'text-red-600', bgColor: 'bg-red-50' },
|
||||
{ name: 'TikTok', description: 'TikTok profile', href: '/tools/tiktok-qr-code', icon: Music, color: 'text-slate-800', bgColor: 'bg-slate-100' },
|
||||
{ name: 'Crypto', description: 'Share wallet address', href: '/tools/crypto-qr-code', icon: Bitcoin, color: 'text-orange-500', bgColor: 'bg-orange-50' },
|
||||
{ name: 'PayPal', description: 'Receive payments', href: '/tools/paypal-qr-code', icon: CreditCard, color: 'text-blue-700', bgColor: 'bg-blue-50' },
|
||||
{ name: 'Zoom', description: 'Join Zoom meeting', href: '/tools/zoom-qr-code', icon: Video, color: 'text-sky-500', bgColor: 'bg-sky-50' },
|
||||
{ name: 'Teams', description: 'Join Teams meeting', href: '/tools/teams-qr-code', icon: Users, color: 'text-violet-500', bgColor: 'bg-violet-50' },
|
||||
{ name: 'Barcode', description: 'Barcode erstellen', href: '/tools/barcode-generator', icon: BarcodeIcon, color: 'text-slate-800', bgColor: 'bg-slate-100' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Server-rendered navigation links for SEO (crawlers) - Placed first for priority */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<nav aria-label="Seitenübersicht">
|
||||
<ul>
|
||||
<li><a href="/">Startseite</a></li>
|
||||
<li><a href="/pricing">Preise</a></li>
|
||||
<li><a href="/blog">Blog</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/login">Anmelden</a></li>
|
||||
<li><a href="/signup">Registrieren</a></li>
|
||||
{/* Tools */}
|
||||
<li><a href="/tools/url-qr-code">URL QR Code</a></li>
|
||||
<li><a href="/tools/text-qr-code">Text QR Code</a></li>
|
||||
<li><a href="/tools/wifi-qr-code">WLAN QR Code</a></li>
|
||||
<li><a href="/tools/vcard-qr-code">vCard QR Code</a></li>
|
||||
<li><a href="/tools/whatsapp-qr-code">WhatsApp QR Code</a></li>
|
||||
<li><a href="/tools/email-qr-code">Email QR Code</a></li>
|
||||
<li><a href="/tools/sms-qr-code">SMS QR Code</a></li>
|
||||
<li><a href="/tools/call-qr-code-generator">Call / Anruf QR Code</a></li>
|
||||
<li><a href="/tools/event-qr-code">Event QR Code</a></li>
|
||||
<li><a href="/tools/geolocation-qr-code">Standort QR Code</a></li>
|
||||
<li><a href="/tools/facebook-qr-code">Facebook QR Code</a></li>
|
||||
<li><a href="/tools/instagram-qr-code">Instagram QR Code</a></li>
|
||||
<li><a href="/tools/twitter-qr-code">Twitter QR Code</a></li>
|
||||
<li><a href="/tools/youtube-qr-code">YouTube QR Code</a></li>
|
||||
<li><a href="/tools/tiktok-qr-code">TikTok QR Code</a></li>
|
||||
<li><a href="/tools/crypto-qr-code">Crypto QR Code</a></li>
|
||||
<li><a href="/tools/paypal-qr-code">PayPal QR Code</a></li>
|
||||
<li><a href="/tools/zoom-qr-code">Zoom QR Code</a></li>
|
||||
<li><a href="/tools/teams-qr-code">Teams QR Code</a></li>
|
||||
<li><a href="/tools/barcode-generator">Barcode Generator</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{/* Header */}
|
||||
<header
|
||||
className="fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-md border-b border-slate-200 shadow-sm"
|
||||
|
||||
>
|
||||
<nav className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl h-20 flex items-center justify-between">
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex items-center space-x-3 group">
|
||||
<div className="relative w-16 h-16 overflow-hidden rounded-full shadow-indigo-200 shadow-lg group-hover:scale-105 transition-transform duration-200">
|
||||
<Image
|
||||
src="/logo.svg"
|
||||
alt="QR Master"
|
||||
fill
|
||||
sizes="64px"
|
||||
className="object-cover"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<span className="text-xl font-bold text-slate-900 tracking-tight group-hover:text-indigo-600 transition-colors">QR Master</span>
|
||||
</Link>
|
||||
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-1">
|
||||
|
||||
{/* Tools Dropdown */}
|
||||
<div
|
||||
className="relative group px-3 py-2"
|
||||
onMouseEnter={() => setToolsOpen(true)}
|
||||
onMouseLeave={() => setToolsOpen(false)}
|
||||
>
|
||||
<button className="flex items-center space-x-1 text-sm font-medium text-slate-600 group-hover:text-slate-900 transition-colors">
|
||||
<span>{t.nav.tools}</span>
|
||||
<ChevronDown className={cn("w-4 h-4 transition-transform duration-200", toolsOpen && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{toolsOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 10 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
className="absolute left-1/2 -translate-x-1/2 top-full mt-2 w-[750px] bg-white rounded-2xl shadow-lg border border-slate-100 p-4 overflow-hidden"
|
||||
>
|
||||
<div className="grid grid-cols-3 gap-1">
|
||||
{tools.map((tool) => (
|
||||
<Link
|
||||
key={tool.name}
|
||||
href={tool.href}
|
||||
className="flex items-center space-x-3 p-2.5 rounded-xl transition-colors hover:bg-slate-50"
|
||||
>
|
||||
<div className={cn("p-2 rounded-lg shrink-0", tool.bgColor, tool.color)}>
|
||||
<tool.icon className="w-4 h-4" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-semibold text-slate-900">{tool.name}</div>
|
||||
<p className="text-xs text-slate-500 leading-snug">{tool.description}</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-3 pt-3 border-t border-slate-100 -mx-4 -mb-4 px-4 py-3 text-center bg-slate-50/50">
|
||||
<p className="text-xs text-slate-500 font-medium">{t.nav.all_free}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<Link href="/#features" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.features}
|
||||
</Link>
|
||||
<Link href="/#pricing" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.pricing}
|
||||
</Link>
|
||||
<Link href="/blog" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.blog}
|
||||
</Link>
|
||||
<Link href="/#faq" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.faq}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="hidden md:flex items-center space-x-4">
|
||||
<Link href="/login" className="text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.login}
|
||||
</Link>
|
||||
|
||||
<Link href="/signup">
|
||||
<Button className={cn(
|
||||
"font-semibold shadow-lg shadow-indigo-500/20 transition-all hover:scale-105",
|
||||
scrolled ? "bg-blue-600 text-white hover:bg-blue-700" : "bg-blue-600 text-white hover:bg-blue-700"
|
||||
)}>
|
||||
{t.nav.cta || "Get Started Free"}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button - Always dark */}
|
||||
<button
|
||||
className="md:hidden p-2 text-slate-900"
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
{mobileMenuOpen ? (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
) : (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
<AnimatePresence>
|
||||
{mobileMenuOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
className="md:hidden bg-white border-b border-slate-100 overflow-hidden"
|
||||
>
|
||||
<div className="container mx-auto px-4 py-6 space-y-2">
|
||||
{/* Free Tools Accordion */}
|
||||
<button
|
||||
onClick={() => setMobileToolsOpen(!mobileToolsOpen)}
|
||||
className="flex items-center justify-between w-full px-4 py-3 rounded-xl hover:bg-slate-50 text-slate-700 font-semibold"
|
||||
>
|
||||
<span>{t.nav.tools}</span>
|
||||
<ChevronDown className={cn("w-5 h-5 transition-transform", mobileToolsOpen && "rotate-180")} />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{mobileToolsOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
exit={{ opacity: 0, height: 0 }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<div className="max-h-[50vh] overflow-y-auto pl-4 space-y-1 border-l-2 border-slate-100 ml-4">
|
||||
{tools.map((tool) => (
|
||||
<Link
|
||||
key={tool.name}
|
||||
href={tool.href}
|
||||
className="flex items-center gap-3 px-4 py-2.5 rounded-lg hover:bg-slate-50 text-slate-600 text-sm"
|
||||
onClick={() => { setMobileMenuOpen(false); setMobileToolsOpen(false); }}
|
||||
>
|
||||
<tool.icon className={cn("w-4 h-4", tool.color)} />
|
||||
{tool.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="h-px bg-slate-100 my-2"></div>
|
||||
|
||||
<Link href="/#features" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.features}</Link>
|
||||
<Link href="/#pricing" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.pricing}</Link>
|
||||
<Link href="/blog" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.blog}</Link>
|
||||
<Link href="/#faq" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.faq}</Link>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 pt-4">
|
||||
<Link href="/login" onClick={() => setMobileMenuOpen(false)}>
|
||||
<Button variant="outline" className="w-full justify-center">{t.nav.login}</Button>
|
||||
</Link>
|
||||
<Link href="/signup" onClick={() => setMobileMenuOpen(false)}>
|
||||
<Button className="w-full justify-center bg-indigo-600 hover:bg-indigo-700">{t.nav.cta}</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</header>
|
||||
|
||||
{/* Main Content */}
|
||||
<main className="pt-20">
|
||||
{children}
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<Footer t={t} />
|
||||
</div >
|
||||
);
|
||||
}
|
||||
@@ -1,452 +0,0 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import {
|
||||
generateFaqSchema,
|
||||
generateSoftwareAppSchema,
|
||||
} from '@/lib/schema-utils';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import de from '@/i18n/de.json';
|
||||
import { FAQ } from '@/components/marketing/FAQ';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import {
|
||||
Barcode as BarcodeIcon,
|
||||
Check,
|
||||
Shield,
|
||||
Zap,
|
||||
Printer,
|
||||
Download,
|
||||
} from 'lucide-react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Barcode Generator Kostenlos – EAN, UPC, Code 128 Online',
|
||||
},
|
||||
description:
|
||||
'Erstellen Sie Barcodes kostenlos online: EAN-13, UPC-A und Code 128. Sofort druckfertig. Für Einzelhandel, Lager und Logistik. Keine Anmeldung erforderlich.',
|
||||
keywords: [
|
||||
'barcode generator',
|
||||
'barcode generator kostenlos',
|
||||
'ean-13 generator',
|
||||
'upc-a generator',
|
||||
'code 128 generator',
|
||||
'barcode erstellen',
|
||||
'barcode online erstellen',
|
||||
'strichcode generator',
|
||||
'barcode für amazon erstellen',
|
||||
'ean barcode generator',
|
||||
'produktbarcode erstellen',
|
||||
'lagerverwaltung barcode',
|
||||
'barcode drucken',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
en: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
de: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Barcode Generator – Kostenlos EAN, UPC & Code 128 erstellen',
|
||||
description:
|
||||
'Barcode Generator: Erstellen Sie professionelle Barcodes für Einzelhandel, Lager und Logistik. Kostenlos, ohne Anmeldung. Sofort druckfertig.',
|
||||
url: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
locale: 'de_DE',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/barcode-generator-preview.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Barcode Generator – Kostenlos Online erstellen',
|
||||
description:
|
||||
'EAN-13, UPC-A und Code 128 Barcodes kostenlos erstellen. Sofort druckfertig.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const faqQuestions = {
|
||||
'Was ist ein Barcode Generator?': {
|
||||
question: 'Was ist ein Barcode Generator?',
|
||||
answer:
|
||||
'Ein Barcode Generator ist ein Online-Tool, das Zahlen oder Texte in scannbare Barcode-Bilder umwandelt. Diese können für Produkte, Etiketten und Inventarsysteme verwendet werden.',
|
||||
},
|
||||
'Ist der Barcode Generator kostenlos?': {
|
||||
question: 'Ist der Barcode Generator kostenlos?',
|
||||
answer:
|
||||
'Ja, unser Barcode Generator ist vollständig kostenlos nutzbar. Sie können Barcodes ohne Anmeldung generieren, herunterladen und drucken.',
|
||||
},
|
||||
'Welches Barcode-Format brauche ich?': {
|
||||
question: 'Welches Barcode-Format brauche ich?',
|
||||
answer:
|
||||
'EAN-13 ist der Standard für Einzelhandel in Europa und weltweit. UPC-A wird hauptsächlich in den USA und Kanada verwendet. Code 128 eignet sich am besten für Logistik und interne Verfolgung, da er Buchstaben und Zahlen unterstützt.',
|
||||
},
|
||||
'Kann ich Barcodes als Vektorgrafik (SVG) herunterladen?': {
|
||||
question: 'Kann ich Barcodes als Vektorgrafik (SVG) herunterladen?',
|
||||
answer:
|
||||
'Ja! SVG-Dateien sind vektorbasiert und können ohne Qualitätsverlust auf jede Größe skaliert werden. Perfekt für professionelle Produktverpackungen und Etiketten.',
|
||||
},
|
||||
'Wie erstelle ich einen Barcode online?': {
|
||||
question: 'Wie erstelle ich einen Barcode online?',
|
||||
answer:
|
||||
'Geben Sie Ihre Produktnummer oder Ihren Text ein, wählen Sie das gewünschte Barcode-Format (z.B. EAN-13 oder Code 128) und der Barcode wird sofort erstellt. Dann können Sie ihn als PNG oder SVG herunterladen.',
|
||||
},
|
||||
'Sind die erstellten Barcodes scannbar?': {
|
||||
question: 'Sind die erstellten Barcodes scannbar?',
|
||||
answer:
|
||||
'Ja, wir generieren standardkonforme Barcodes, die von jedem handelsüblichen Barcode-Scanner gelesen werden können, einschließlich Smartphone-Kamera-Apps.',
|
||||
},
|
||||
'Kann ich diese Barcodes für Amazon verwenden?': {
|
||||
question: 'Kann ich diese Barcodes für Amazon verwenden?',
|
||||
answer:
|
||||
'Sie können hier das Barcode-Bild erstellen, wenn Sie bereits eine gültige EAN/UPC-Nummer haben. Offizielle GS1-Registrierungsnummern erhalten Sie jedoch nur direkt bei GS1, um Produkte auf Amazon oder in großen Einzelhandelssystemen zu listen.',
|
||||
},
|
||||
'Was ist der Unterschied zwischen Barcode und QR-Code?': {
|
||||
question: 'Was ist der Unterschied zwischen Barcode und QR-Code?',
|
||||
answer:
|
||||
'Ein Barcode speichert Daten horizontal (1D) und wird hauptsächlich für Produktkennungen verwendet. Ein QR-Code speichert Daten in 2D (Matrix) und kann viel mehr Informationen enthalten, wie URLs, Kontaktdaten oder WLAN-Zugangsdaten.',
|
||||
},
|
||||
'Kann ich mehrere Barcodes gleichzeitig erstellen?': {
|
||||
question: 'Kann ich mehrere Barcodes gleichzeitig erstellen?',
|
||||
answer:
|
||||
'Ja, mit einem PRO-Account können Sie mehrere Barcodes gleichzeitig generieren. Dies ist ideal für große Produktmengen oder Lagerverwaltung.',
|
||||
},
|
||||
'Was ist eine Prüfziffer bei Barcodes?': {
|
||||
question: 'Was ist eine Prüfziffer bei Barcodes?',
|
||||
answer:
|
||||
'Die Prüfziffer ist die letzte Ziffer in einem Barcode, die mathematisch aus den anderen Ziffern berechnet wird. Sie stellt sicher, dass der Barcode korrekt gescannt wird, selbst wenn er leicht beschädigt oder verkratzt ist.',
|
||||
},
|
||||
};
|
||||
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'Barcode Generator',
|
||||
'Erstellen Sie druckfertige Barcodes für EAN, UPC, Code 128 und weitere Formate. Kostenlos und ohne Anmeldung.',
|
||||
'/barcode-generator-preview.png',
|
||||
'UtilitiesApplication'
|
||||
),
|
||||
generateFaqSchema(faqQuestions),
|
||||
],
|
||||
};
|
||||
|
||||
export default function BarcodeGeneratorDEPage() {
|
||||
const t = de;
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
|
||||
{/* SEO Content für Suchmaschinen */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
QR Masters kostenloser Barcode Generator ermöglicht es Ihnen,
|
||||
professionelle Barcodes für Produkte, Etiketten und Inventarsysteme zu
|
||||
erstellen. Unterstützt EAN-13 für europäischen Einzelhandel, UPC-A für
|
||||
US-Markt und Code 128 für Logistik und interne Verwendung. Alle
|
||||
Barcodes sind standardkonform und sofort druckfertig.
|
||||
</p>
|
||||
<p>
|
||||
Unser Barcode Generator funktioniert vollständig im Browser. Keine
|
||||
Software-Installation erforderlich. Exportieren Sie Ihre Barcodes als
|
||||
PNG für den sofortigen Druck oder als SVG für professionelle
|
||||
Verpackungsdesigns. Perfekt für kleine Unternehmen, Online-Händler und
|
||||
Lagerverwaltung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative bg-gradient-to-b from-slate-900 to-slate-800 text-white py-16 md:py-24">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" width="100%" height="100%">
|
||||
<defs>
|
||||
<pattern
|
||||
id="barcode_pattern_de"
|
||||
width="60"
|
||||
height="60"
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<path
|
||||
d="M5 0 V 60 M15 0 V 60 M20 0 V 60 M35 0 V 60 M40 0 V 60 M55 0 V 60"
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
strokeOpacity="0.5"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#barcode_pattern_de)" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl relative z-10">
|
||||
<div className="max-w-3xl mx-auto text-center">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-400"></span>
|
||||
</span>
|
||||
Kostenloses Tool – Professionell & Schnell
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight mb-6">
|
||||
Kostenloser{' '}
|
||||
<span className="text-blue-400">Barcode Generator</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-slate-300 mb-8 leading-relaxed">
|
||||
Erstellen Sie professionelle Barcodes in Sekunden. Für{' '}
|
||||
<strong className="text-white">
|
||||
Einzelhandel, Lager und Logistik
|
||||
</strong>
|
||||
. Unterstützt EAN-13, UPC-A und Code 128. Keine Anmeldung
|
||||
erforderlich.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-4 text-sm font-medium">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Einzelhandel-fähig
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
SVG-Export
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Ohne Anmeldung
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Generator Section */}
|
||||
<section className="py-12 px-4 bg-slate-100">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<div className="text-center mb-6">
|
||||
<h2 className="text-2xl font-bold mb-2">Barcode jetzt erstellen</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Geben Sie Ihre Daten ein und laden Sie den Barcode herunter
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-3xl shadow-xl overflow-hidden border border-slate-200">
|
||||
<div className="bg-slate-900 px-6 py-3 flex items-center gap-2">
|
||||
<div className="flex gap-1.5">
|
||||
<div className="w-3 h-3 rounded-full bg-red-500"></div>
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||||
<div className="w-3 h-3 rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<span className="text-white/60 text-sm ml-2">
|
||||
qrmaster.net/tools/barcode-generator
|
||||
</span>
|
||||
</div>
|
||||
<iframe
|
||||
src="https://www.qrmaster.net/tools/barcode-generator"
|
||||
className="w-full h-[650px] border-0"
|
||||
title="Barcode Generator"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-center mt-6">
|
||||
<a
|
||||
href="https://www.qrmaster.net/tools/barcode-generator"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<span>Vollbild öffnen</span>
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Barcode Types Info */}
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">
|
||||
Barcode-Formate im Überblick
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">EAN-13</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Internationaler Standard für Einzelhandel. 13 Ziffern, weltweit
|
||||
anerkannt.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> Produkte in Europa & global
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">UPC-A</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Amerikanischer Standard. 12 Ziffern, hauptsächlich in
|
||||
Nordamerika.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> USA & Kanada Einzelhandel
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-purple-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">Code 128</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Flexible Lösung für Logistik. Alphanumerisch, hohe Datendichte.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> Versand, Lager, Inventar
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* How It Works */}
|
||||
<section className="py-16 px-4 bg-slate-50">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">
|
||||
So funktioniert unser Barcode Generator
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-5 gap-8">
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
1
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Daten eingeben</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Geben Sie Ihre Produktnummer oder Text ein.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
2
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Format wählen</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
EAN-13, UPC-A oder Code 128 auswählen.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
3
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Vorschau</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Barcode wird in Echtzeit aktualisiert.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
4
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Herunterladen</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Als PNG oder SVG speichern.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
5
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Drucken</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Sofort auf Etiketten drucken.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Use Cases */}
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-4">
|
||||
Für wen ist unser Barcode Generator geeignet?
|
||||
</h2>
|
||||
<p className="text-center text-muted-foreground mb-12 max-w-2xl mx-auto">
|
||||
Ob Kleinunternehmer, Online-Händler oder Lagerverwaltung – unser
|
||||
Tool unterstützt Sie bei allen Barcode-Bedarfen.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Printer className="w-8 h-8 text-blue-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Einzelhandel</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
EAN-13 Barcodes für Produktetiketten im stationären Handel.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Shield className="w-8 h-8 text-green-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">E-Commerce</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
UPC/EAN für Amazon, eBay und andere Marktplätze.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Zap className="w-8 h-8 text-orange-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Lager & Logistik</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Code 128 für interne Bestandsverfolgung und Versand.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Download className="w-8 h-8 text-purple-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Druckerei</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
SVG-Export für professionelle Verpackungsdesigns.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ Section */}
|
||||
<FAQ
|
||||
t={{
|
||||
faq: { title: 'Häufig gestellte Fragen', questions: faqQuestions },
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
{/* Scroll to Top */}
|
||||
<ScrollToTop />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
import '@/styles/globals.css';
|
||||
import { Providers } from '@/components/Providers';
|
||||
import MarketingDeLayout from './MarketingDeLayout';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import FacebookPixel from '@/components/analytics/FacebookPixel';
|
||||
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: {
|
||||
@@ -13,14 +13,14 @@ export const metadata: Metadata = {
|
||||
},
|
||||
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',
|
||||
},
|
||||
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',
|
||||
@@ -55,33 +55,33 @@ export const metadata: Metadata = {
|
||||
'facebook-domain-verification': process.env.NEXT_PUBLIC_FACEBOOK_DOMAIN_VERIFICATION || '',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default function MarketingDeGroupLayout({
|
||||
children,
|
||||
}: {
|
||||
};
|
||||
|
||||
export default function MarketingDeGroupLayout({
|
||||
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()) }}
|
||||
<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>
|
||||
/>
|
||||
<MarketingDeLayout>
|
||||
{children}
|
||||
</MarketingDeLayout>
|
||||
</Providers>
|
||||
</Suspense>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import type { Metadata } from 'next';
|
||||
import { useCasePagesDe } from '@/lib/growth-pages-de';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import { generateFaqSchema } from '@/lib/schema-utils';
|
||||
@@ -136,7 +138,7 @@ export default function QRCodeErstellenPage() {
|
||||
<h3 className="font-semibold text-lg mb-2">Speisekarten QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Ideal für Restaurants, Cafés und Bars. Gäste scannen den Code und
|
||||
sehen Ihre Speisekarte digital auf dem Handy –无需接触实物菜单。
|
||||
sehen Ihre Speisekarte digital auf dem Handy.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
@@ -266,6 +268,31 @@ export default function QRCodeErstellenPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Beliebte Anwendungsfälle - interne Verlinkung auf deutsche Use-Case-Seiten */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl py-12">
|
||||
<h2 className="text-3xl font-bold text-center mb-3">
|
||||
Beliebte Anwendungsfälle
|
||||
</h2>
|
||||
<p className="text-center text-muted-foreground mb-8">
|
||||
Ausführliche Anleitungen für Ihren Einsatzzweck – mit Checklisten und
|
||||
praxisnahen FAQs.
|
||||
</p>
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{Object.values(useCasePagesDe).map((useCase) => (
|
||||
<Link
|
||||
key={useCase.slug}
|
||||
href={useCase.href}
|
||||
className="group p-6 border rounded-lg transition-colors hover:border-slate-300 hover:bg-slate-50"
|
||||
>
|
||||
<h3 className="font-semibold text-lg mb-2 group-hover:text-blue-600 transition-colors">
|
||||
{useCase.title}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">{useCase.summary}</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Answer First Block (SEO/AEO) - German */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
<AnswerFirstBlock
|
||||
|
||||
110
src/app/de/[slug]/page.tsx
Normal file
110
src/app/de/[slug]/page.tsx
Normal 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
79
src/app/de/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
85
src/app/de/preise/page.tsx
Normal file
85
src/app/de/preise/page.tsx
Normal 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
publishedComparisonPages,
|
||||
publishedGuidePages,
|
||||
} from '../lib/pseo-published-pages';
|
||||
import { publishedUseCases } from '../lib/growth-pages';
|
||||
import { useCasePagesDe } from '../lib/growth-pages-de';
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const baseUrl = 'https://www.qrmaster.net';
|
||||
@@ -32,6 +34,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
'paypal-qr-code',
|
||||
'zoom-qr-code',
|
||||
'teams-qr-code',
|
||||
'google-review-qr-code',
|
||||
'barcode-generator',
|
||||
];
|
||||
|
||||
@@ -58,6 +61,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
|
||||
const highPriorityTools: Record<string, number> = {
|
||||
'barcode-generator': 0.95,
|
||||
'google-review-qr-code': 0.9,
|
||||
};
|
||||
|
||||
const toolLastModified: Record<string, Date> = {
|
||||
@@ -111,66 +115,25 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
changeFrequency: 'weekly' as const,
|
||||
priority: 0.9,
|
||||
},
|
||||
...publishedUseCases.map((useCase) => ({
|
||||
url: `${baseUrl}${useCase.href}`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
})),
|
||||
// German pages under /de
|
||||
{
|
||||
url: `${baseUrl}/use-cases/restaurant-menu-qr-codes`,
|
||||
url: `${baseUrl}/de/preise`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/business-card-qr-codes`,
|
||||
...Object.values(useCasePagesDe).map((useCase) => ({
|
||||
url: `${baseUrl}${useCase.href}`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/event-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/flyer-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/packaging-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/real-estate-sign-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/feedback-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/qr-codes-for-review-collection`,
|
||||
lastModified: new Date('2026-05-11'),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/payment-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/use-cases/coupon-qr-codes`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
},
|
||||
})),
|
||||
{
|
||||
url: `${baseUrl}/qr-code-for-marketing-campaigns`,
|
||||
lastModified: new Date(),
|
||||
|
||||
Reference in New Issue
Block a user