import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { ArrowRight, CheckCircle2, ClipboardCheck, Gauge, RefreshCw } from "lucide-react"; import Breadcrumbs, { type BreadcrumbItem } from "@/components/Breadcrumbs"; import SeoJsonLd from "@/components/SeoJsonLd"; import { getGuidePage } from "@/lib/guide-pages"; import type { GuidePage } from "@/lib/pseo-page-types"; import { isPublishedGuideSlug, publishedGuidePages, } from "@/lib/pseo-published-pages"; import { articleSchema, breadcrumbSchema, faqPageSchema } from "@/lib/schema"; const SITE_URL = "https://www.qrmaster.net"; const LAST_MODIFIED = "2026-06-22"; type PageProps = { params: { slug: string; }; }; export const dynamicParams = false; export function generateStaticParams() { return publishedGuidePages.map((page) => ({ slug: page.slug })); } function getPublishedPage(slug: string): GuidePage { if (!isPublishedGuideSlug(slug)) { notFound(); } const page = getGuidePage(slug); if (!page) { notFound(); } return page; } function titleFor(page: GuidePage) { if (page.slug === "dynamic-qr-code-best-practices") { return "Dynamic QR Code Best Practices"; } return page.title; } function descriptionFor(page: GuidePage) { if (page.slug === "dynamic-qr-code-best-practices") { return "Plan dynamic QR codes with better naming, tracking, print testing, privacy checks, and update workflows before campaigns go live."; } return page.description; } export function generateMetadata({ params }: PageProps): Metadata { const page = getPublishedPage(params.slug); const title = titleFor(page); const description = descriptionFor(page); const canonical = `${SITE_URL}${page.canonicalPath}`; return { title: { absolute: title, }, description, alternates: { canonical, languages: { "x-default": canonical, en: canonical, }, }, robots: { index: true, follow: true, }, 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: { title, description, url: canonical, type: "article", images: ["/og-image.png"], }, twitter: { title, description, }, }; } function breadcrumbsFor(page: GuidePage): BreadcrumbItem[] { return [ { name: "Home", url: "/" }, { name: page.title, url: page.canonicalPath }, ]; } function howToStructuredData(page: GuidePage) { return { "@context": "https://schema.org", "@type": "HowTo", "@id": `${SITE_URL}${page.canonicalPath}#howto`, name: titleFor(page), description: descriptionFor(page), datePublished: LAST_MODIFIED, dateModified: LAST_MODIFIED, totalTime: "PT15M", author: { "@type": "Organization", name: "QR Master", url: SITE_URL, }, step: page.howToSteps.map((step, index) => ({ "@type": "HowToStep", position: index + 1, name: `Step ${index + 1}`, text: step, })), }; } function PracticeRail() { const items = [ { label: "Before print", detail: "Name the QR by campaign, surface, and destination risk.", icon: ClipboardCheck, }, { label: "During launch", detail: "Test the printed asset on real devices and final material.", icon: Gauge, }, { label: "After launch", detail: "Review scan context before changing or reprinting assets.", icon: RefreshCw, }, ]; return (
Operating rhythm
{items.map((item) => { const Icon = item.icon; return (

{item.label}

{item.detail}

); })}
); } export default function GuidePageRoute({ params }: PageProps) { const page = getPublishedPage(params.slug); const title = titleFor(page); const description = descriptionFor(page); const canonical = `${SITE_URL}${page.canonicalPath}`; const breadcrumbs = breadcrumbsFor(page); const structuredData = [ articleSchema({ headline: title, description, datePublished: LAST_MODIFIED, dateModified: LAST_MODIFIED, author: "QR Master", url: canonical, image: `${SITE_URL}/og-image.png`, }), howToStructuredData(page), faqPageSchema(page.faq), breadcrumbSchema(breadcrumbs), ]; return ( <>

Dynamic QR operating guide

{title}

{page.quickAnswer}

{page.primaryCta.label} {page.secondaryCta.label}

The working principle

{page.intro} A dynamic QR code is strongest when the team treats the printed asset, the destination, and the reporting convention as one workflow.

{page.keyTakeaways.map((item) => (
))}

Dynamic QR setup sequence

Start with naming and placement. Tracking data only becomes useful when the scan can be traced back to a real campaign, surface, or operational context.

    {page.howToSteps.map((step, index) => (
  1. 0{index + 1}

    {step}

  2. ))}
{page.checklist && (

{page.checklist.title}

Use this before the QR code reaches print. Most expensive QR mistakes are workflow mistakes, not image-generation mistakes.

    {page.checklist.items.map((item) => (
  • ))}
)}

Pages to pair with this guide

These companion pages cover the buying decision, tracking setup, and the product workflow behind dynamic QR codes.

{page.relatedLinks.map((link) => (

{link.title}

{link.description}

Open page ))}

Common questions

{page.faq.map((item) => (
{item.question} +

{item.answer}

))}
); }