diff --git a/docs/automations/runs/qrmaster-seo-sprint-2026-06-22.md b/docs/automations/runs/qrmaster-seo-sprint-2026-06-22.md new file mode 100644 index 0000000..42d0597 --- /dev/null +++ b/docs/automations/runs/qrmaster-seo-sprint-2026-06-22.md @@ -0,0 +1,255 @@ +# QRMaster SEO Sprint: Dynamic QR Buying Decision + +Run date: 2026-06-22 +Automation: QRMaster SEO Sprint Machine +Mode: recommendation and PR-ready tasks only, no publishing + +## Inputs Used + +- `docs/automations/qrmaster-seo-sprint-machine.md` +- `docs/automations/qrmaster-pr-seo-review.md` +- `.agents/product-marketing-context.md` +- `marketing/programmatic-seo-top-50.md` +- `seo-keywords.csv` +- `src/lib/comparison-pages.ts` +- `src/lib/guide-pages.ts` +- `src/app/sitemap.ts` +- `src/app/robots.ts` + +Missing requested input: `marketing/keyword-strategy-seo-plan.md` is not present in this worktree. Scoring used `seo-keywords.csv`, `marketing/programmatic-seo-top-50.md`, and repo inspection instead. + +## PLAN + +1. Understand the task: run a controlled weekly SEO sprint without publishing. +2. Identify affected files: pSEO page data, route templates, sitemap, robots, and target money pages. +3. Design the implementation: select one cluster and expose only approved pages through allowlisted routes. +4. Implement step-by-step: prepare PR-ready tasks, not direct changes. +5. Verify results: use the PR SEO review checklist before merge. + +## Cluster Selection + +Selected cluster: Dynamic QR buying decision. + +Rationale: This cluster owns the highest commercial decision point for QR Master: static/free one-off generation versus dynamic, editable, trackable QR workflows. It also avoids repeating last week's tracking package while still reusing the same route/template investment. The top two backlog entries are both in this cluster, and their content already exists in `src/lib/comparison-pages.ts` but is not exposed because there is no `/compare/[slug]` route. + +Important implementation note: `src/lib/comparison-pages.ts` and `src/lib/guide-pages.ts` contain more records than this sprint should publish. The PR should use an explicit published-slug allowlist or `status` field so only the selected pages become reachable and indexable. + +## Candidate Cluster Scores + +Scores use the automation model: product fit 30, commercial intent 25, differentiation potential 15, cluster leverage 10, search winability 10, production effort 10. + +| Cluster | Product fit | Commercial intent | Differentiation | Cluster leverage | Winability | Effort | Score | Decision | +|---|---:|---:|---:|---:|---:|---:|---:|---| +| Dynamic QR buying decision | 30 | 24 | 14 | 10 | 8 | 8 | 94 | Select | +| Tracking and analytics | 29 | 23 | 14 | 9 | 8 | 7 | 90 | Defer, already selected last run | +| Bulk QR and spreadsheet workflows | 26 | 21 | 12 | 8 | 9 | 8 | 84 | Next after route scaffold | +| Print reliability | 23 | 15 | 12 | 8 | 9 | 8 | 75 | Support cluster | +| Restaurant/menu QR | 25 | 18 | 11 | 8 | 6 | 7 | 75 | Hold for industry sprint | + +## Selected Work + +| Type | URL | Score | Reason | +|---|---|---:|---| +| New comparison page | `/compare/dynamic-vs-static-qr-codes` | 94 | Highest leverage concept page. Explains why QR Master's dynamic/edit-after-print value exists. | +| New comparison page | `/compare/free-vs-paid-qr-code-generator` | 91 | Bottom-funnel upgrade page. Connects free QR intent to pricing, dynamic limits, analytics, and reprint risk. | +| New guide page | `/guide/dynamic-qr-code-best-practices` | 88 | Strategic support guide. Helps AI/search systems connect dynamic QR setup, naming, tracking, and print workflows. | +| Refresh existing page | `/dynamic-qr-code-generator` | 92 | Money page. Strong volume in CSV: `dynamic qr code`, `dynamic qr code generator`, `create dynamic qr code`, `dynamic qr generator`, and `dynamic qr code creator` are each 1k-10k. | +| Refresh existing page | `/reprint-calculator` | 84 | Conversion-support page. Should quantify the central "static QR reprint cost" argument for comparison pages. | + +## Keyword Intent And Fan-Out + +| URL | Primary keyword | Intent | Fan-out subtopics | +|---|---|---|---| +| `/compare/dynamic-vs-static-qr-codes` | dynamic vs static QR codes | Commercial investigation | Can static QR codes be edited, what dynamic QR tracking means, reprint risk, when static is enough, print campaigns, menus, packaging, privacy-aware analytics, cost tradeoff, migration from static to dynamic. | +| `/compare/free-vs-paid-qr-code-generator` | free vs paid QR code generator | Commercial investigation | Free static generators, dynamic QR limits, paid plan features, tracking, branding, expiry risk, scan limits, pricing, hidden reprint cost, business use cases, when free is enough. | +| `/guide/dynamic-qr-code-best-practices` | dynamic QR code best practices | Informational to commercial | Naming conventions, campaign grouping, editable destinations, scan tracking setup, QR placement, UTM usage, print testing, destination updates, privacy/GDPR framing, internal reporting. | +| `/dynamic-qr-code-generator` | dynamic QR code generator | Transactional | Create dynamic QR, editable QR code, free dynamic QR limits, tracking, update after print, branding, plan limits, static vs dynamic, use cases, schema-backed FAQ. | +| `/reprint-calculator` | QR code reprint cost calculator | Commercial utility | Static QR risk, reprint math, edit-after-print savings, campaign examples, pricing comparison, calculator assumptions, what to do after calculating savings. | + +## Recommended New Pages + +### 1. `/compare/dynamic-vs-static-qr-codes` + +PR status: content data exists in `src/lib/comparison-pages.ts`; needs route/template, metadata, schema, sitemap entry, and internal links. + +Title: `Dynamic vs Static QR Codes: Which to Use` + +H1: `Dynamic vs Static QR Codes` + +Meta description: `Compare dynamic and static QR codes for editability, scan tracking, reprint risk, and business workflows before you print.` + +Slug: `/compare/dynamic-vs-static-qr-codes` + +Direct answer: Static QR codes lock the destination into the image. Dynamic QR codes route through a managed link, so teams can change the destination and measure scans after the QR code has been printed. + +Schema opportunities: `Article`, `FAQPage`, `BreadcrumbList`, and `ItemList` for the comparison table. + +Visual: Responsive comparison table plus a simple redirect-flow diagram: printed QR -> QR Master redirect -> current destination. + +### 2. `/compare/free-vs-paid-qr-code-generator` + +PR status: content data exists in `src/lib/comparison-pages.ts`; needs route/template, metadata, schema, sitemap entry, and internal links. + +Title: `Free vs Paid QR Code Generator` + +H1: `Free vs Paid QR Code Generator` + +Meta description: `See when a free QR generator is enough and when paid dynamic QR features, tracking, branding, and reprint savings are worth it.` + +Slug: `/compare/free-vs-paid-qr-code-generator` + +Direct answer: A free QR generator is usually enough for one permanent static link. A paid QR platform becomes worth it when the code is printed at scale, tied to campaigns, or needs editing and analytics later. + +Schema opportunities: `Article`, `FAQPage`, `BreadcrumbList`, and `ItemList`. + +Visual: "Free is enough when..." versus "Paid is worth it when..." table. + +### 3. `/guide/dynamic-qr-code-best-practices` + +PR status: content data exists in `src/lib/guide-pages.ts`; needs route/template, metadata, schema, sitemap entry, and internal links. + +Title: `Dynamic QR Code Best Practices` + +H1: `Dynamic QR Code Best Practices` + +Meta description: `Plan dynamic QR codes with better naming, tracking, print testing, privacy checks, and update workflows before campaigns go live.` + +Slug: `/guide/dynamic-qr-code-best-practices` + +Direct answer: The best dynamic QR workflows use clear naming, stable print placement, measurable destinations, and disciplined update management after the code is in circulation. + +Schema opportunities: `Article`, `HowTo`, `FAQPage`, and `BreadcrumbList`. + +Visual: Checklist or workflow graphic for naming -> print test -> publish -> monitor -> update. + +## Recommended Page Refreshes + +### `/dynamic-qr-code-generator` + +Refresh rationale: This is the money page for the cluster and already ranks against high-volume dynamic QR terms. It has strong answer-first structure, schema, FAQs, and internal links, but should be tightened before more internal equity points to it. + +PR-ready tasks: + +- Shorten title under roughly 60 characters if possible. Current absolute title is likely too long. +- Verify current plan limits against product/business truth before publishing. Product context says Free includes 8 dynamic codes, but app copy often says 3 active dynamic codes. +- Re-check competitor pricing and claims before keeping comparison table language. +- Replace or verify weak research/stat blocks. Avoid unsupported numbers such as broad print-error claims unless a reliable source is attached. +- Add contextual links to the two new comparison pages and the new best-practices guide. +- Ensure each major H2 starts with a direct answer in the first sentence. + +### `/reprint-calculator` + +Refresh rationale: This page supports the strongest conversion argument for dynamic QR: printed assets should not become waste when URLs change. + +PR-ready tasks: + +- Update title to target the query directly: `QR Code Reprint Cost Calculator`. +- Add an answer-first block explaining when static QR reprints become expensive. +- Add FAQ content and `FAQPage` schema for "Can I edit a QR code after printing?", "How much do QR reprints cost?", and "When is dynamic QR worth it?" +- Link to `/compare/dynamic-vs-static-qr-codes`, `/compare/free-vs-paid-qr-code-generator`, `/dynamic-qr-code-generator`, and `/pricing`. +- Add visible assumptions around calculator inputs so AI/search systems can cite the methodology. +- Keep calculator lightweight. Do not add heavy chart libraries or large images. + +## Internal-Link Plan + +Add links from: + +- `/dynamic-qr-code-generator` to `/compare/dynamic-vs-static-qr-codes`, `/compare/free-vs-paid-qr-code-generator`, `/guide/dynamic-qr-code-best-practices`, and `/reprint-calculator`. +- `/reprint-calculator` to `/compare/dynamic-vs-static-qr-codes`, `/dynamic-qr-code-generator`, and `/pricing`. +- `/qr-code-tracking` to `/compare/dynamic-vs-static-qr-codes` where dynamic tracking is explained. +- `/qr-code-analytics` to `/guide/dynamic-qr-code-best-practices` where naming and placement discipline are discussed. +- `/pricing` to `/compare/free-vs-paid-qr-code-generator` with anchor text like `free vs paid QR generator`. +- `/tools/url-qr-code` to `/compare/dynamic-vs-static-qr-codes` if the tool page discusses static output or destination changes. + +Add links from new pages to: + +- `/dynamic-qr-code-generator` +- `/qr-code-tracking` +- `/qr-code-analytics` +- `/reprint-calculator` +- `/pricing` +- `/guide/dynamic-qr-code-best-practices` + +Anchor text should be natural and varied: `dynamic QR code generator`, `track QR code scans`, `compare free and paid QR generators`, `estimate reprint savings`, `dynamic QR best practices`. + +## PR Plan + +1. Add controlled route templates: + - `src/app/(main)/compare/[slug]/page.tsx` + - `src/app/(main)/guide/[slug]/page.tsx` +2. Add published-slug allowlists: + - comparisons: `dynamic-vs-static-qr-codes`, `free-vs-paid-qr-code-generator` + - guides: `dynamic-qr-code-best-practices` +3. Route behavior: + - `generateStaticParams` returns only published slugs. + - Unknown or unpublished slugs call `notFound()`. + - Metadata uses page title, description, canonical path, Open Graph, and no accidental `noindex`. +4. Template behavior: + - One H1. + - Direct answer block near top. + - H2/H3 sections start with answer-first language. + - Responsive comparison tables with horizontal overflow on mobile. + - CTA blocks point to selected commercial pages. +5. Schema: + - Comparison pages: `Article`, `FAQPage`, `BreadcrumbList`, `ItemList`. + - Guide page: `Article`, `HowTo`, `FAQPage`, `BreadcrumbList`. +6. Sitemap: + - Add selected `/compare/...` and `/guide/...` URLs only. + - Use current sprint date for `lastModified`. +7. Refresh pages: + - Update `/dynamic-qr-code-generator`. + - Update `/reprint-calculator`. +8. Review gate: + - Run the PR SEO review from `docs/automations/qrmaster-pr-seo-review.md`. + - Do not merge until high-severity SEO/conversion findings are resolved. + +## Robots And Indexing Assumptions + +- `src/app/robots.ts` currently allows public pages and explicitly allows `OAI-SearchBot`, `GPTBot`, `ChatGPT-User`, `PerplexityBot`, `ClaudeBot`, `anthropic-ai`, and `Google-Extended` while blocking private paths. +- Selected pages should be indexable, canonicalized, and included in `sitemap.ts`. +- Unselected `comparisonPages` and `guidePages` records should remain unpublished until a human approves them. +- For pages that should not appear, prefer route allowlisting or `notFound()` rather than relying on robots.txt. + +External guidance checked: + +- Google SEO Starter Guide: https://developers.google.com/search/docs/fundamentals/seo-starter-guide +- Google AI features and your website: https://developers.google.com/search/docs/appearance/ai-features +- Google structured data introduction: https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data +- Google robots.txt guidance: https://developers.google.com/search/docs/crawling-indexing/robots/intro +- OpenAI crawler overview: https://developers.openai.com/api/docs/bots +- OpenAI publisher/developer FAQ for ChatGPT search inclusion: https://help.openai.com/en/articles/12627856-publishers-and-developers-faq + +## Mobile, Visual, And Speed Checks + +- Keep comparison tables responsive with `overflow-x-auto` and a minimum readable width. +- Avoid new heavyweight images unless they are compressed and useful. +- Use existing lightweight cards, tables, and schema components. +- Validate CTA tap targets on mobile. +- Do not add animated hero assets or charting libraries for this sprint. + +## Verification Checklist + +- `npm run lint` +- `npm run build` +- Confirm exactly one H1 per selected page. +- Confirm metadata title, description, canonical, and Open Graph are set. +- Confirm selected pages are in `sitemap.ts`. +- Confirm unpublished pSEO records are not reachable. +- Confirm robots rules do not block selected public pages. +- Validate JSON-LD output for comparison and guide pages. +- Check internal links and CTA destinations manually. +- Check mobile rendering for comparison tables and CTA blocks. +- Run the QRMaster PR SEO Review checklist and request changes for any high-severity finding. + +## Follow-Up Social And Outreach Ideas + +1. LinkedIn post: "Static QR codes are cheap until the printed URL changes." Link to the dynamic-vs-static comparison. +2. X thread: "Free QR generators are enough for one-off links. Here is when paid dynamic QR becomes cheaper." Link to free-vs-paid. +3. Quora answer: "Can you change a QR code after printing?" Explain static vs dynamic and link to the comparison. +4. Short YouTube/Loom: show a printed flyer scenario, change the QR destination, and show scan tracking. +5. Outreach pitch: send the reprint calculator to print shops, small agencies, and restaurant consultants as a utility they can reference. + +## Hold For Future Sprints + +- Tracking and analytics cluster from the 2026-06-15 run remains valid, but do not duplicate the same package. The same guide route scaffold can later expose `/guide/how-to-track-qr-code-scans`, `/guide/how-to-use-utm-with-qr-codes`, and `/guide/qr-code-gdpr`. +- Next good cluster after this PR: Bulk QR and spreadsheet workflows, because `bulk qr code generator`, `mass qr code generator`, and `qr code generator excel` show strong search fit and low competition in `seo-keywords.csv`. diff --git a/next.config.mjs b/next.config.mjs index 79f295c..c7e09fe 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -34,18 +34,34 @@ const nextConfig = { pagesBufferLength: 2, }, poweredByHeader: false, - webpack: (config, { dev }) => { - if (!dev && isWslOnWindowsMount()) { - config.cache = { - type: 'filesystem', - cacheDirectory: path.join(os.tmpdir(), 'qrmaster-next-webpack-cache'), + webpack: (config, { dev }) => { + if (!dev && isWslOnWindowsMount()) { + config.cache = { + type: 'filesystem', + cacheDirectory: path.join(os.tmpdir(), 'qrmaster-next-webpack-cache'), }; } - - return config; - }, - async redirects() { - return [ + + return config; + }, + async headers() { + const longCacheHeaders = [ + { + key: 'Cache-Control', + value: 'public, max-age=31536000, immutable', + }, + ]; + + return [ + { source: '/favicon1.png', headers: longCacheHeaders }, + { source: '/favicon.svg', headers: longCacheHeaders }, + { source: '/favicon.ico', headers: longCacheHeaders }, + { source: '/logo.svg', headers: longCacheHeaders }, + { source: '/producthunt-featured.svg', headers: longCacheHeaders }, + ]; + }, + async redirects() { + return [ { source: '/create-qr', destination: '/dynamic-qr-code-generator', diff --git a/public/favicon1.png b/public/favicon1.png index b6f209a..82c6181 100644 Binary files a/public/favicon1.png and b/public/favicon1.png differ diff --git a/public/producthunt-featured.svg b/public/producthunt-featured.svg new file mode 100644 index 0000000..d90c411 --- /dev/null +++ b/public/producthunt-featured.svg @@ -0,0 +1,11 @@ + + QR Master on Product Hunt + Featured Product Hunt badge for QR Master + + + + + Featured on + Product Hunt + #3 + diff --git a/src/app/(main)/(app)/layout.tsx b/src/app/(main)/(app)/layout.tsx index 78cc8e7..5cf728f 100644 --- a/src/app/(main)/(app)/layout.tsx +++ b/src/app/(main)/(app)/layout.tsx @@ -10,7 +10,7 @@ export const metadata: Metadata = { robots: { index: false, follow: false }, icons: { icon: [ - { url: '/favicon1.png', sizes: '2048x2048', type: 'image/png' }, + { url: '/favicon1.png', sizes: '512x512', type: 'image/png' }, ], shortcut: '/favicon1.png', apple: '/favicon1.png', diff --git a/src/app/(main)/(marketing)/MarketingLayout.tsx b/src/app/(main)/(marketing)/MarketingLayout.tsx index e1d971d..cd86288 100644 --- a/src/app/(main)/(marketing)/MarketingLayout.tsx +++ b/src/app/(main)/(marketing)/MarketingLayout.tsx @@ -6,12 +6,10 @@ import { usePathname } from 'next/navigation'; import { Button } from '@/components/ui/Button'; import { Footer } from '@/components/ui/Footer'; import en from '@/i18n/en.json'; -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 { cn } from '@/lib/utils'; -import { AnimatePresence, motion } from 'framer-motion'; -import { allUseCases } from '@/lib/growth-pages'; -import { industryPages } from '@/lib/industry-pages'; -import Image from 'next/image'; +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 { cn } from '@/lib/utils'; +import { AnimatePresence, motion } from 'framer-motion'; +import Image from 'next/image'; export default function MarketingLayout({ children, @@ -80,83 +78,26 @@ export default function MarketingLayout({ return (
- {/* Server-rendered navigation links for SEO (crawlers) - Placed first for priority */} -
- -
- {/* Header */}