feat: implement marketing comparison and alternatives hub with dedicated competitor landing pages

This commit is contained in:
Timo Knuth
2026-04-08 15:38:02 +02:00
parent a6fd2ed61f
commit 14c3cde7e6
10 changed files with 3569 additions and 4 deletions

View File

@@ -0,0 +1,181 @@
import React from 'react';
import type { Metadata } from 'next';
import Link from 'next/link';
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
import SeoJsonLd from '@/components/SeoJsonLd';
import { breadcrumbSchema } from '@/lib/schema';
import { MarketingPageTracker, TrackedCtaLink } from '@/components/marketing/MarketingAnalytics';
import { Button } from '@/components/ui/Button';
import { Card } from '@/components/ui/Card';
export const metadata: Metadata = {
title: {
absolute: 'QR Code Platform Alternatives | QR Master',
},
description:
'Compare QR Master with QR-Code-Generator.com, Flowcode, Beaconstac / Uniqode, and Bitly. Find the right QR alternative for pricing, branding, analytics, and bulk creation.',
alternates: {
canonical: 'https://www.qrmaster.net/alternatives',
},
openGraph: {
title: 'QR Code Platform Alternatives | QR Master',
description:
'Clean comparisons for the most common QR code platform alternatives, from pricing traps to branding limits and enterprise overkill.',
url: 'https://www.qrmaster.net/alternatives',
type: 'website',
images: ['/og-image.png'],
},
twitter: {
title: 'QR Code Platform Alternatives | QR Master',
description:
'Compare QR Master with Flowcode, Bitly, Beaconstac / Uniqode, and QR-Code-Generator.com.',
},
};
const breadcrumbItems: BreadcrumbItem[] = [
{ name: 'Home', url: '/' },
{ name: 'Alternatives', url: '/alternatives' },
];
const pageSchema = {
'@context': 'https://schema.org',
'@type': 'CollectionPage',
name: 'QR Code Platform Alternatives',
url: 'https://www.qrmaster.net/alternatives',
description:
'Comparison pages for QR Master versus major QR code and adjacent link-management platforms.',
};
const alternativePages = [
{
href: '/alternatives/qr-code-generator',
eyebrow: 'Trial trap',
title: 'QR-Code-Generator.com Alternative',
description:
'For teams burned by 14-day dynamic QR trials and forced annual upgrades after print is already live.',
},
{
href: '/alternatives/flowcode',
eyebrow: 'Brand control',
title: 'Flowcode Alternative',
description:
'For brands and agencies that need clean QR codes without third-party logos or branded scan interstitials.',
},
{
href: '/alternatives/beaconstac',
eyebrow: 'SMB fit',
title: 'Beaconstac / Uniqode Alternative',
description:
'For smaller teams that want reliable analytics and bulk QR creation without paying enterprise-platform pricing.',
},
{
href: '/alternatives/bitly',
eyebrow: 'QR-first workflow',
title: 'Bitly Alternative',
description:
'For campaigns where QR codes are the main workflow, not a side feature hidden inside a link shortener.',
},
];
export default function AlternativesHubPage() {
return (
<>
<SeoJsonLd data={[pageSchema, breadcrumbSchema(breadcrumbItems)]} />
<MarketingPageTracker pageType="commercial" cluster="competitor" />
<div className="min-h-screen" style={{ backgroundColor: '#F8F7F4', color: '#18181B' }}>
<section className="border-b bg-white" style={{ borderColor: '#E4E0D9' }}>
<div className="container mx-auto max-w-7xl px-4 pb-20 pt-10 sm:px-6 lg:px-8">
<div className="mb-10">
<Breadcrumbs items={breadcrumbItems} />
</div>
<div className="max-w-3xl">
<div
className="mb-6 inline-block rounded px-3 py-1.5 text-xs font-semibold uppercase tracking-widest"
style={{ backgroundColor: '#DCFCE7', color: '#166534', letterSpacing: '0.12em' }}
>
QR Master alternatives
</div>
<h1
className="mb-6 text-4xl font-extrabold leading-[1.08] tracking-tight sm:text-5xl"
style={{ color: '#111110' }}
>
Clean comparisons for the QR platforms people actually switch from.
</h1>
<p className="mb-8 text-lg leading-relaxed" style={{ color: '#52525B' }}>
Some tools hide trial limits. Some force their brand into your scan flow. Some are simply priced for
enterprise teams. These pages break down where each platform fits, where it does not, and when QR
Master is the better tradeoff.
</p>
<div className="flex flex-col gap-3 sm:flex-row">
<TrackedCtaLink
href="/signup"
ctaLabel="Start Free"
ctaLocation="hero_primary"
pageType="commercial"
cluster="competitor"
>
<Button size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
Start Free
</Button>
</TrackedCtaLink>
<TrackedCtaLink
href="/pricing"
ctaLabel="See Pricing"
ctaLocation="hero_secondary"
pageType="commercial"
cluster="competitor"
>
<Button variant="outline" size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
See Pricing
</Button>
</TrackedCtaLink>
</div>
</div>
</div>
</section>
<section className="py-24" style={{ backgroundColor: '#F8F7F4' }}>
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mb-12 max-w-3xl">
<h2 className="mb-4 text-3xl font-bold tracking-tight sm:text-4xl" style={{ color: '#111110' }}>
Explore Alternatives
</h2>
<p className="text-lg" style={{ color: '#71717A' }}>
Pick the comparison that matches the problem you are trying to solve.
</p>
</div>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
{alternativePages.map((item) => (
<Link key={item.href} href={item.href} className="group block">
<Card
className="h-full rounded-xl border bg-white p-7 shadow-none transition-transform duration-150 group-hover:-translate-y-1"
style={{ borderColor: '#E4E0D9' }}
>
<p
className="mb-4 text-xs font-semibold uppercase tracking-widest"
style={{ color: '#71717A', letterSpacing: '0.12em' }}
>
{item.eyebrow}
</p>
<h3 className="mb-3 text-xl font-bold" style={{ color: '#18181B' }}>
{item.title}
</h3>
<p className="text-sm leading-relaxed" style={{ color: '#52525B' }}>
{item.description}
</p>
<p className="mt-6 text-sm font-semibold" style={{ color: '#166534' }}>
Open comparison
</p>
</Card>
</Link>
))}
</div>
</div>
</section>
</div>
</>
);
}