GSC seo
This commit is contained in:
548
linear.app/DESIGN.md
Normal file
548
linear.app/DESIGN.md
Normal file
@@ -0,0 +1,548 @@
|
||||
---
|
||||
version: alpha
|
||||
name: Linear
|
||||
description: "A near-black product-focused marketing canvas built around #010102 (the deepest dark surface of any tool in this collection), light gray text (#f7f8f8), and the signature Linear lavender-blue (#5e6ad2) used as the single chromatic accent. The system reads as software-craft documentation: dense, technical, and quietly luxurious. Display type is set in the Linear custom sans (SF Pro Display fallback) at 500–700 with measured negative tracking. Cards live as charcoal panels (#0f1011) with hairline borders. The accent lavender appears on the brand mark, focus rings, and a few intentional CTAs — never decoratively. Page rhythm leans on product UI screenshots framed in dark panels rather than atmospheric color."
|
||||
|
||||
colors:
|
||||
primary: "#5e6ad2"
|
||||
on-primary: "#ffffff"
|
||||
primary-hover: "#828fff"
|
||||
primary-focus: "#5e69d1"
|
||||
ink: "#f7f8f8"
|
||||
ink-muted: "#d0d6e0"
|
||||
ink-subtle: "#8a8f98"
|
||||
ink-tertiary: "#62666d"
|
||||
canvas: "#010102"
|
||||
surface-1: "#0f1011"
|
||||
surface-2: "#141516"
|
||||
surface-3: "#18191a"
|
||||
surface-4: "#191a1b"
|
||||
hairline: "#23252a"
|
||||
hairline-strong: "#34343a"
|
||||
hairline-tertiary: "#3e3e44"
|
||||
inverse-canvas: "#ffffff"
|
||||
inverse-surface-1: "#f5f6f6"
|
||||
inverse-surface-2: "#f6f7f7"
|
||||
inverse-ink: "#000000"
|
||||
brand-secure: "#7a7fad"
|
||||
semantic-success: "#27a644"
|
||||
semantic-overlay: "#000000"
|
||||
|
||||
typography:
|
||||
display-xl:
|
||||
fontFamily: Linear Display
|
||||
fontSize: 80px
|
||||
fontWeight: 600
|
||||
lineHeight: 1.05
|
||||
letterSpacing: -3.0px
|
||||
display-lg:
|
||||
fontFamily: Linear Display
|
||||
fontSize: 56px
|
||||
fontWeight: 600
|
||||
lineHeight: 1.10
|
||||
letterSpacing: -1.8px
|
||||
display-md:
|
||||
fontFamily: Linear Display
|
||||
fontSize: 40px
|
||||
fontWeight: 600
|
||||
lineHeight: 1.15
|
||||
letterSpacing: -1.0px
|
||||
headline:
|
||||
fontFamily: Linear Display
|
||||
fontSize: 28px
|
||||
fontWeight: 600
|
||||
lineHeight: 1.20
|
||||
letterSpacing: -0.6px
|
||||
card-title:
|
||||
fontFamily: Linear Display
|
||||
fontSize: 22px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.25
|
||||
letterSpacing: -0.4px
|
||||
subhead:
|
||||
fontFamily: Linear Display
|
||||
fontSize: 20px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.40
|
||||
letterSpacing: -0.2px
|
||||
body-lg:
|
||||
fontFamily: Linear Text
|
||||
fontSize: 18px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.50
|
||||
letterSpacing: -0.1px
|
||||
body:
|
||||
fontFamily: Linear Text
|
||||
fontSize: 16px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.50
|
||||
letterSpacing: -0.05px
|
||||
body-sm:
|
||||
fontFamily: Linear Text
|
||||
fontSize: 14px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.50
|
||||
letterSpacing: 0
|
||||
caption:
|
||||
fontFamily: Linear Text
|
||||
fontSize: 12px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.40
|
||||
letterSpacing: 0
|
||||
button:
|
||||
fontFamily: Linear Text
|
||||
fontSize: 14px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.20
|
||||
letterSpacing: 0
|
||||
eyebrow:
|
||||
fontFamily: Linear Text
|
||||
fontSize: 13px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.30
|
||||
letterSpacing: 0.4px
|
||||
mono:
|
||||
fontFamily: Linear Mono
|
||||
fontSize: 13px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.50
|
||||
letterSpacing: 0
|
||||
|
||||
rounded:
|
||||
xs: 4px
|
||||
sm: 6px
|
||||
md: 8px
|
||||
lg: 12px
|
||||
xl: 16px
|
||||
xxl: 24px
|
||||
pill: 9999px
|
||||
full: 9999px
|
||||
|
||||
spacing:
|
||||
xxs: 4px
|
||||
xs: 8px
|
||||
sm: 12px
|
||||
md: 16px
|
||||
lg: 24px
|
||||
xl: 32px
|
||||
xxl: 48px
|
||||
section: 96px
|
||||
|
||||
components:
|
||||
button-primary:
|
||||
backgroundColor: "{colors.primary}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 8px 14px
|
||||
button-primary-pressed:
|
||||
backgroundColor: "{colors.primary-focus}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.md}"
|
||||
button-primary-hover:
|
||||
backgroundColor: "{colors.primary-hover}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.md}"
|
||||
button-secondary:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 8px 14px
|
||||
button-tertiary:
|
||||
backgroundColor: "{colors.canvas}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 8px 14px
|
||||
button-inverse:
|
||||
backgroundColor: "{colors.inverse-canvas}"
|
||||
textColor: "{colors.inverse-ink}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 8px 14px
|
||||
pricing-card:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 24px
|
||||
pricing-card-featured:
|
||||
backgroundColor: "{colors.surface-2}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 24px
|
||||
feature-card:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 24px
|
||||
product-screenshot-card:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.xl}"
|
||||
padding: 24px
|
||||
testimonial-card:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-lg}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 32px
|
||||
customer-logo-tile:
|
||||
backgroundColor: "{colors.canvas}"
|
||||
textColor: "{colors.ink-subtle}"
|
||||
typography: "{typography.caption}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 16px
|
||||
text-input:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 8px 12px
|
||||
text-input-focused:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 8px 12px
|
||||
pricing-tab-default:
|
||||
backgroundColor: "{colors.canvas}"
|
||||
textColor: "{colors.ink-subtle}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 6px 14px
|
||||
pricing-tab-selected:
|
||||
backgroundColor: "{colors.surface-2}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.button}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 6px 14px
|
||||
cta-banner:
|
||||
backgroundColor: "{colors.surface-1}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.headline}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 48px
|
||||
changelog-row:
|
||||
backgroundColor: "{colors.canvas}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 24px 0
|
||||
status-badge:
|
||||
backgroundColor: "{colors.surface-2}"
|
||||
textColor: "{colors.ink-muted}"
|
||||
typography: "{typography.caption}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 2px 8px
|
||||
top-nav:
|
||||
backgroundColor: "{colors.canvas}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-sm}"
|
||||
rounded: "{rounded.xs}"
|
||||
height: 56px
|
||||
footer:
|
||||
backgroundColor: "{colors.canvas}"
|
||||
textColor: "{colors.ink-subtle}"
|
||||
typography: "{typography.caption}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 64px 32px
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Linear's marketing canvas is the deepest dark surface in this collection — `{colors.canvas}` is #010102, essentially pure black with a faint blue tint. On top sits a four-step surface ladder (`{colors.surface-1}` through `{colors.surface-4}`) for cards, panels, and lifted tiles, with hairline borders running from `{colors.hairline}` (#23252a) up through `{colors.hairline-strong}` and `{colors.hairline-tertiary}`. Light gray text (`{colors.ink}` #f7f8f8) carries the body and headlines.
|
||||
|
||||
The single chromatic accent is **Linear lavender-blue** `{colors.primary}` (#5e6ad2) — used on the brand mark, focus rings, and the primary CTA button. A lighter hover state (`{colors.primary-hover}` #828fff) and a focus-tinted variant (`{colors.primary-focus}` #5e69d1) extend the same hue. Linear avoids saturated greens, oranges, reds, etc. on the marketing canvas — the only semantic color is `{colors.semantic-success}` (#27a644) for status pills and the rare success indicator.
|
||||
|
||||
Display type runs Linear's custom sans (with `SF Pro Display` fallback) at weight 500–700 with negative letter-spacing scaling from -3.0px at 80px down to 0 at body. The body family is Linear's text cut, and a Linear Mono is reserved for code snippets in product screenshots.
|
||||
|
||||
The page rhythm is **dense product screenshots** — Linear's marketing leads with high-fidelity captures of the product UI (issue list, project view, dashboard) framed in `{colors.surface-1}` panels with `{rounded.xl}` 16px corners. The chrome is intentionally minimal so the app screenshots can do the heavy lifting.
|
||||
|
||||
**Key Characteristics:**
|
||||
- **Dark-canvas marketing system** — `{colors.canvas}` (#010102) is the deepest dark in this collection.
|
||||
- **Lavender-blue brand accent** (`{colors.primary}` #5e6ad2) — used scarcely on brand mark, focus, and the primary CTA.
|
||||
- Four-step surface ladder (canvas → surface-1 → surface-2 → surface-3 → surface-4) carries hierarchy without shadow.
|
||||
- Display tracking pulls aggressively negative (-3.0px at 80px); body holds at -0.05px.
|
||||
- Cards use `{rounded.lg}` 12px corners with 1px hairline borders — never pill, rarely 16px.
|
||||
- **Product UI screenshots** dominate the page. The marketing chrome is a dark frame for the app.
|
||||
- No second chromatic color. No atmospheric gradients. No spotlight cards.
|
||||
|
||||
## Colors
|
||||
|
||||
> Source pages: linear.app (home), /intake, /pricing, /contact/sales, /build.
|
||||
|
||||
### Brand & Accent
|
||||
- **Lavender-Blue** ({colors.primary}): The signature Linear accent — primary CTA, brand mark, link emphasis.
|
||||
- **Lavender Hover** ({colors.primary-hover}): Lighter lavender (#828fff) — hovered state of the primary CTA.
|
||||
- **Lavender Focus** ({colors.primary-focus}): Focus-ring tint (#5e69d1) — focused inputs, focused buttons.
|
||||
- **Brand Secure** ({colors.brand-secure}): Muted lavender-gray (#7a7fad) — used in "Linear Security" surfaces.
|
||||
|
||||
### Surface
|
||||
- **Canvas** ({colors.canvas}): Default page background — #010102, near-pure black with a faint blue tint.
|
||||
- **Surface 1** ({colors.surface-1}): One step above canvas — feature cards, pricing cards, product screenshot panels.
|
||||
- **Surface 2** ({colors.surface-2}): Two steps above — featured pricing card, hovered cards.
|
||||
- **Surface 3** ({colors.surface-3}): Three steps above — line-tertiary backgrounds, sub-nav.
|
||||
- **Surface 4** ({colors.surface-4}): Four steps above — bg-level-3, deepest lifted surface.
|
||||
- **Hairline** ({colors.hairline}): 1px borders on cards and dividers.
|
||||
- **Hairline Strong** ({colors.hairline-strong}): Stronger 1px borders — input focus rings.
|
||||
- **Hairline Tertiary** ({colors.hairline-tertiary}): Tertiary borders for nested surfaces.
|
||||
- **Inverse Canvas** ({colors.inverse-canvas}): Pure white — surface of the inverse pill CTA on a small set of section openers.
|
||||
- **Inverse Surface 1** ({colors.inverse-surface-1}): One step above inverse canvas.
|
||||
- **Inverse Surface 2** ({colors.inverse-surface-2}): Two steps above inverse canvas.
|
||||
|
||||
### Text
|
||||
- **Ink** ({colors.ink}): All headlines and emphasized body type — light gray #f7f8f8.
|
||||
- **Ink Muted** ({colors.ink-muted}): Secondary type at #d0d6e0 — meta info on hero panels.
|
||||
- **Ink Subtle** ({colors.ink-subtle}): Tertiary type at #8a8f98 — deselected pricing tabs, footer columns.
|
||||
- **Ink Tertiary** ({colors.ink-tertiary}): Quaternary at #62666d — disabled, footnotes.
|
||||
|
||||
### Semantic
|
||||
- **Success Green** ({colors.semantic-success}): Status pills, success indicators. The only semantic color on marketing.
|
||||
- **Overlay** ({colors.semantic-overlay}): Pure black overlay scrim for modals.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font Family
|
||||
|
||||
- **Linear Display** — Linear's custom display sans; fallback `SF Pro Display, -apple-system, system-ui, Segoe UI, Roboto`. Carries display-xl through subhead.
|
||||
- **Linear Text** — Linear's custom text sans (a slightly different cut tuned for body sizes); same fallback stack. Carries body sizes, button labels, captions.
|
||||
- **Linear Mono** — Linear's custom mono; fallback `ui-monospace, SF Mono, Menlo`. Used for code snippets in product screenshots and for status / ID tokens.
|
||||
|
||||
The marketing surface treats Display and Text as one continuous voice; the family change is silent.
|
||||
|
||||
### Hierarchy
|
||||
|
||||
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|
||||
|---|---|---|---|---|---|
|
||||
| `{typography.display-xl}` | 80px | 600 | 1.05 | -3.0px | Largest hero headline |
|
||||
| `{typography.display-lg}` | 56px | 600 | 1.10 | -1.8px | Section opener headlines |
|
||||
| `{typography.display-md}` | 40px | 600 | 1.15 | -1.0px | Sub-section headlines |
|
||||
| `{typography.headline}` | 28px | 600 | 1.20 | -0.6px | Pricing tier titles, CTA banner heading |
|
||||
| `{typography.card-title}` | 22px | 500 | 1.25 | -0.4px | Feature card title |
|
||||
| `{typography.subhead}` | 20px | 400 | 1.40 | -0.2px | Lead body, intro paragraphs |
|
||||
| `{typography.body-lg}` | 18px | 400 | 1.50 | -0.1px | Hero subhead, lead paragraphs |
|
||||
| `{typography.body}` | 16px | 400 | 1.50 | -0.05px | Default body |
|
||||
| `{typography.body-sm}` | 14px | 400 | 1.50 | 0 | Card body, footer columns |
|
||||
| `{typography.caption}` | 12px | 400 | 1.40 | 0 | Captions, meta, status |
|
||||
| `{typography.button}` | 14px | 500 | 1.20 | 0 | All button labels |
|
||||
| `{typography.eyebrow}` | 13px | 500 | 1.30 | 0.4px | Section eyebrow (slight positive tracking) |
|
||||
| `{typography.mono}` | 13px | 400 | 1.50 | 0 | Linear Mono for code in product screenshots |
|
||||
|
||||
### Principles
|
||||
|
||||
- **Aggressive negative tracking on display** (-3.0px at 80px ≈ 4% of size).
|
||||
- **Single voice from display to body.** Display-xl at 600 → body at 400 — same family, narrower weights.
|
||||
- **Eyebrow uses positive tracking** (+0.4px) — contrast against the negative-tracked display marks the eyebrow as taxonomy.
|
||||
- **Mono only in code contexts.** Linear Mono lives inside product screenshots — not on marketing chrome.
|
||||
|
||||
### Note on Font Substitutes
|
||||
|
||||
Linear's custom typeface isn't publicly distributed; the documented fallback `SF Pro Display, -apple-system, system-ui` is the recommended substitute on macOS. For cross-platform implementation, **Inter** at weight 500 / 600 / 700 is the closest free substitute. **Geist Sans** is also viable. For mono, **JetBrains Mono** or **Geist Mono** at weight 400 closely approximates Linear Mono.
|
||||
|
||||
## Layout
|
||||
|
||||
### Spacing System
|
||||
|
||||
- **Base unit**: 4px.
|
||||
- **Tokens (front matter)**: `{spacing.xxs}` 4px · `{spacing.xs}` 8px · `{spacing.sm}` 12px · `{spacing.md}` 16px · `{spacing.lg}` 24px · `{spacing.xl}` 32px · `{spacing.xxl}` 48px · `{spacing.section}` 96px.
|
||||
- Card interior padding: `{spacing.lg}` 24px on feature/pricing cards; `{spacing.xl}` 32px on testimonial cards; `{spacing.xxl}` 48px on CTA banners.
|
||||
- Pill button padding: 8px vertical · 14px horizontal — Linear's compact button spec.
|
||||
- Form input padding: 8px vertical · 12px horizontal.
|
||||
|
||||
### Grid & Container
|
||||
|
||||
- Max content width sits around 1280px.
|
||||
- Card grids are 3-up at desktop, 2-up at tablet, 1-up at mobile.
|
||||
- Pricing tier grid is 3-up; comparison strip below shows checkmarks per tier.
|
||||
- Product screenshot panels span full content width — they're the protagonist.
|
||||
|
||||
### Whitespace Philosophy
|
||||
|
||||
The dark canvas IS the whitespace. Sections separate by lift onto surface-1 panels, not by gaps in white. Within a panel, generous `{spacing.lg}` 24px gaps between content blocks; `{spacing.section}` 96px between sections.
|
||||
|
||||
## Elevation & Depth
|
||||
|
||||
| Level | Treatment | Use |
|
||||
|---|---|---|
|
||||
| 0 (flat) | No shadow, no border | Default for body type, hero text, footer |
|
||||
| 1 (charcoal lift) | `{colors.surface-1}` background on canvas, 1px `{colors.hairline}` | Default cards, product panels |
|
||||
| 2 (surface-2 lift) | `{colors.surface-2}` background, 1px `{colors.hairline-strong}` | Featured pricing card, hovered cards |
|
||||
| 3 (surface-3 lift) | `{colors.surface-3}` background | Sub-nav, dropdown menus |
|
||||
| 4 (focus ring) | 2px `{colors.primary-focus}` outline at 50% opacity | Focused input, focused button |
|
||||
|
||||
Linear's depth is carried by surface ladder + hairline borders. The brand resists drop shadows on dark almost entirely.
|
||||
|
||||
### Decorative Depth
|
||||
|
||||
- **Product UI screenshots** dominate as decorative depth.
|
||||
- **No atmospheric gradients, no spotlight cards.**
|
||||
- **Subtle white edge highlight** on the top edge of lifted panels — gives the dark surface a faint "pixel rendered" feel.
|
||||
|
||||
## Shapes
|
||||
|
||||
### Border Radius Scale
|
||||
|
||||
| Token | Value | Use |
|
||||
|---|---|---|
|
||||
| `{rounded.xs}` | 4px | Small chips, status badges |
|
||||
| `{rounded.sm}` | 6px | Inline tags |
|
||||
| `{rounded.md}` | 8px | All buttons, form inputs |
|
||||
| `{rounded.lg}` | 12px | Pricing cards, feature cards, testimonial cards |
|
||||
| `{rounded.xl}` | 16px | Product screenshot panels |
|
||||
| `{rounded.xxl}` | 24px | Oversized CTA banners (rare) |
|
||||
| `{rounded.pill}` | 9999px | Pricing tab toggles, status pills |
|
||||
| `{rounded.full}` | 9999px | Avatar circles |
|
||||
|
||||
### Photography & Illustration Geometry
|
||||
|
||||
- Product UI screenshots dominate; they sit in `{rounded.xl}` 16px tiles with `{spacing.lg}` 24px outer padding.
|
||||
- Customer logo tiles render at small sizes (~24px logo height) on `{colors.canvas}` with no border.
|
||||
- Avatar circles in testimonial cards use `{rounded.full}` at 32–40px sizes.
|
||||
|
||||
## Components
|
||||
|
||||
### Buttons
|
||||
|
||||
**`button-primary`** — Lavender CTA. The default primary CTA across all pages.
|
||||
- Background `{colors.primary}`, text `{colors.on-primary}`, type `{typography.button}`, padding 8px 14px, rounded `{rounded.md}`.
|
||||
- Pressed state lives in `button-primary-pressed` (background shifts to `{colors.primary-focus}`).
|
||||
- Hover state lives in `button-primary-hover` (background shifts to `{colors.primary-hover}` lighter lavender).
|
||||
|
||||
**`button-secondary`** — Charcoal button. Used for secondary CTAs ("Sign in", "Read changelog").
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.button}`, padding 8px 14px, rounded `{rounded.md}`. 1px `{colors.hairline}` border.
|
||||
|
||||
**`button-tertiary`** — Plain text button.
|
||||
- Background `{colors.canvas}`, text `{colors.ink}`, type `{typography.button}`, rounded `{rounded.md}`, padding 8px 14px.
|
||||
|
||||
**`button-inverse`** — White-on-dark inverse CTA.
|
||||
- Background `{colors.inverse-canvas}`, text `{colors.inverse-ink}`, type `{typography.button}`, rounded `{rounded.md}`, padding 8px 14px.
|
||||
|
||||
### Pricing Tabs
|
||||
|
||||
**`pricing-tab-default`** + **`pricing-tab-selected`** — Pill-toggle on `/pricing`.
|
||||
- Default: `{colors.canvas}` background, `{colors.ink-subtle}` text, rounded `{rounded.pill}`, padding 6px 14px.
|
||||
- Selected: `{colors.surface-2}` background, `{colors.ink}` text — selected = surface lift.
|
||||
|
||||
### Cards & Containers
|
||||
|
||||
**`pricing-card`** — Each tier on `/pricing`.
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.lg}`, padding 24px. 1px `{colors.hairline}` border.
|
||||
|
||||
**`pricing-card-featured`** — Recommended tier — surface lift to surface-2.
|
||||
- Background `{colors.surface-2}`, otherwise identical structure.
|
||||
|
||||
**`feature-card`** — Generic feature highlight tile.
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.lg}`, padding 24px.
|
||||
|
||||
**`product-screenshot-card`** — The dominant card type — frames a high-fidelity Linear app UI screenshot.
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.xl}`, padding 24px.
|
||||
|
||||
**`testimonial-card`** — Customer quote with avatar + name + role.
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body-lg}`, rounded `{rounded.lg}`, padding 32px.
|
||||
|
||||
**`customer-logo-tile`** — Small tile in the customer marquee.
|
||||
- Background `{colors.canvas}`, text `{colors.ink-subtle}`, type `{typography.caption}`, rounded `{rounded.xs}`, padding 16px.
|
||||
|
||||
**`cta-banner`** — Closing CTA panel near page bottom.
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.headline}`, rounded `{rounded.lg}`, padding 48px.
|
||||
|
||||
### Inputs & Forms
|
||||
|
||||
**`text-input`** + **`text-input-focused`** — Form fields on `/contact/sales` and signup overlays.
|
||||
- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.md}`, padding 8px 12px.
|
||||
- Focused state retains the same surface; the focus ring is a 2px `{colors.primary-focus}` outline at 50% opacity.
|
||||
|
||||
### Status & Build Page
|
||||
|
||||
**`changelog-row`** — Each row in `/build` (changelog page) listing version, date, and changes.
|
||||
- Background `{colors.canvas}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.xs}`, padding 24px 0. 1px `{colors.hairline}` bottom rule.
|
||||
|
||||
**`status-badge`** — Small status pill.
|
||||
- Background `{colors.surface-2}`, text `{colors.ink-muted}`, type `{typography.caption}`, rounded `{rounded.pill}`, padding 2px 8px.
|
||||
|
||||
### Navigation
|
||||
|
||||
**`top-nav`** — Sticky dark bar with the Linear wordmark left, primary nav links centered, and a `button-secondary` ("Sign in") + `button-primary` ("Get started") pair right.
|
||||
- Background `{colors.canvas}`, text `{colors.ink}`, type `{typography.body-sm}`, height 56px.
|
||||
|
||||
### Footer
|
||||
|
||||
**`footer`** — Dense link grid on `{colors.canvas}` with the Linear wordmark left.
|
||||
- Background `{colors.canvas}`, text `{colors.ink-subtle}`, type `{typography.caption}`, padding 64px 32px.
|
||||
|
||||
## Do's and Don'ts
|
||||
|
||||
### Do
|
||||
|
||||
- Reserve `{colors.canvas}` (#010102) as the system's anchor surface — the faint blue tint is intentional.
|
||||
- Use `{colors.primary}` lavender ONLY for: brand mark, primary CTA, focus ring, link emphasis.
|
||||
- Use the four-step surface ladder for hierarchy. Avoid skipping levels.
|
||||
- Pair display weight 600 with body weight 400 — Linear resists 700+ display weights.
|
||||
- Apply negative letter-spacing aggressively on display.
|
||||
- Use product UI screenshots as the protagonist of every section.
|
||||
- Compose CTAs as `{rounded.md}` 8px corners.
|
||||
|
||||
### Don't
|
||||
|
||||
- Don't ship a light-mode marketing page.
|
||||
- Don't use lavender as a section background or card fill.
|
||||
- Don't introduce a second chromatic accent (orange, pink, green for marketing).
|
||||
- Don't add atmospheric gradients or spotlight cards.
|
||||
- Don't pill-round CTAs.
|
||||
- Don't use `#000000` true black as the canvas.
|
||||
- Don't combine multiple bright accents in product screenshot mockups.
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
### Breakpoints
|
||||
|
||||
| Name | Width | Key Changes |
|
||||
|---|---|---|
|
||||
| Desktop-XL | 1440px | Default desktop layout |
|
||||
| Desktop | 1280px | Card grid 3-up maintained |
|
||||
| Tablet | 1024px | Card grid 3-up → 2-up |
|
||||
| Mobile-Lg | 768px | Pricing comparison becomes accordion; nav hamburger |
|
||||
| Mobile | 480px | Single-column; display-xl scales 80px → ~36px |
|
||||
|
||||
### Touch Targets
|
||||
|
||||
- CTAs hold ≥40px tap height across viewports.
|
||||
- Pricing tab pills hold ≥36px tap height; touch viewports grow to ≥44px.
|
||||
- Form inputs hold ≥44px tap target on touch.
|
||||
|
||||
### Collapsing Strategy
|
||||
|
||||
- **Top nav**: links collapse to hamburger below 768px.
|
||||
- **Card grids**: 3-up → 2-up at 1024px → 1-up below 768px.
|
||||
- **Pricing comparison**: per-tier accordion below 768px.
|
||||
- **Display type**: `{typography.display-xl}` 80px scales toward `{typography.display-md}` 40px on mobile.
|
||||
|
||||
### Image Behavior
|
||||
|
||||
- Product UI screenshots maintain aspect ratio and never crop.
|
||||
- Customer logos in the marquee may collapse from 6-up to 3-up below 768px.
|
||||
|
||||
## Iteration Guide
|
||||
|
||||
1. Focus on ONE component at a time and reference it by its `components:` token name.
|
||||
2. When introducing a section, decide first which surface lift it lives on.
|
||||
3. Default body to `{typography.body}` at weight 400.
|
||||
4. Run `npx @google/design.md lint DESIGN.md` after edits.
|
||||
5. Add new variants as separate component entries.
|
||||
6. Treat lavender as scarce: brand mark, primary CTA, focus, link emphasis.
|
||||
7. Lead every section with a product UI screenshot.
|
||||
|
||||
## Known Gaps
|
||||
|
||||
- The four-step surface ladder values are extracted directly from Linear's `--color-bg-level-3`, `--color-line-tint`, etc. CSS variables; they are Linear's canonical surface spec.
|
||||
- Form-field error and validation styling is not visible on the inspected pages.
|
||||
- Light mode is not documented because the marketing site does not ship a light theme.
|
||||
- Linear's actual product UI uses a richer color-tag palette (red, orange, yellow, green, blue, purple) for issue priorities and project labels — those colors live in the in-product surfaces shown in mockups.
|
||||
- The custom display, text, and mono families are proprietary; an open-source substitute is acceptable.
|
||||
41
memory/upgrade_nudge_status.md
Normal file
41
memory/upgrade_nudge_status.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Upgrade Nudge Status Memory
|
||||
|
||||
Last updated: 2026-05-02
|
||||
|
||||
Purpose: local memory for upgrade-nudge outreach status when SMTP/Sent-folder evidence is incomplete. `sent_assumed_manual` means the user instructed us to treat the contact as already sent for future filtering, not that a verifiable SMTP/Sent record was found.
|
||||
|
||||
## Pending send
|
||||
|
||||
These are the two highest-priority upgrade candidates. Do not mark as sent until the upgrade email is actually sent.
|
||||
|
||||
| Name | Email | Stage | Lead score | Reason |
|
||||
| --- | --- | --- | ---: | --- |
|
||||
| Ishemupenyu Chagonda | info@aldenadvisory.co.uk | Upgrade Candidate | 105 | User confirmed no upgrade email has been sent yet |
|
||||
| Shreya Hegde | shhegde@linkedin.com | Upgrade Candidate | 95 | User confirmed no upgrade email has been sent yet |
|
||||
|
||||
## Marked as sent by manual memory
|
||||
|
||||
These contacts should be treated as already sent when filtering future upgrade-nudge batches.
|
||||
|
||||
| Name | Email | Stage | Lead score | Status |
|
||||
| --- | --- | --- | ---: | --- |
|
||||
| Marcos Pagan | marcos@easternalliancerealty.com | Upgrade Candidate | 80 | sent_assumed_manual |
|
||||
| katie Loucaides | katie.loucaides@rya.org.uk | Upgrade Candidate | 70 | sent_assumed_manual |
|
||||
| Lindsey Holtz | lholtz@uwhealth.org | Upgrade Candidate | 70 | sent_assumed_manual |
|
||||
| Janell Elder | janell.elder@gov.sk.ca | Upgrade Candidate | 70 | sent_assumed_manual |
|
||||
| Nouf Saud | nouna.1428@gmail.com | Hot | 65 | sent_assumed_manual |
|
||||
| Richie Shawl | richie.shawl@alfalaval.com | Hot | 60 | sent_assumed_manual |
|
||||
| Patricia Hartmann | patricia.hartmann@agderfk.no | Hot | 60 | sent_assumed_manual |
|
||||
| Andreas Knuth | andreas.knuth@gmail.com | Hot | unknown | sent_assumed_manual |
|
||||
|
||||
## Excluded
|
||||
|
||||
| Name | Email | Stage | Reason |
|
||||
| --- | --- | --- | --- |
|
||||
| Profoto Malaysia Sdn Bhd | profotomalaysia@gmail.com | Paid | Already PRO/Paid, not an upgrade-nudge target |
|
||||
|
||||
## Notes
|
||||
|
||||
- IMAP `Sent` check on 2026-05-02 found no verifiable Day-7 upgrade-nudge email records.
|
||||
- The currently configured database lacks the `upgradeNudgeSentAt` column, so app-level sent status could not be verified there.
|
||||
- Future upgrade-nudge sends should prioritize `info@aldenadvisory.co.uk` and `shhegde@linkedin.com`.
|
||||
@@ -8,11 +8,11 @@ import { CheckCircle2, Shield, Users, BarChart3, Globe, Lock } from 'lucide-reac
|
||||
import { ObfuscatedMailto } from '@/components/ui/ObfuscatedMailto';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'About QR Master | The Team & Mission Behind the Platform',
|
||||
description: 'QR Master is built for measurable campaigns and secure QR code operations. Learn about our mission, values, and why businesses trust us.',
|
||||
title: 'About QR Master | Free QR Code Generator for Businesses',
|
||||
description: 'QR Master helps businesses create, track, and manage QR codes at scale — free dynamic QR codes, real analytics, and no hidden limits. Learn who we are.',
|
||||
openGraph: {
|
||||
title: 'About QR Master | Dynamic QR Codes & Analytics',
|
||||
description: 'We help businesses create, manage, and track QR codes at scale. Transparent pricing, privacy-first, and built for reliability.',
|
||||
title: 'About QR Master | Free Dynamic QR Codes & Analytics',
|
||||
description: 'Free dynamic QR codes with scan analytics, custom branding, and no reprint headaches. Learn about the team and mission behind QR Master.',
|
||||
url: 'https://www.qrmaster.net/about',
|
||||
type: 'website',
|
||||
images: ['/og-image.png'],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,9 +14,9 @@ function truncateAtWord(text: string, maxLength: number): string {
|
||||
}
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const title = truncateAtWord('QR Code FAQ: Do QR Codes Expire, Work Through Laminate, and More', 60);
|
||||
const title = truncateAtWord('QR Code FAQ: Expiry, Laminate Scanning & Dynamic QR Explained', 60);
|
||||
const description = truncateAtWord(
|
||||
'Answers to common QR code questions: do QR codes expire, will they become obsolete, do they work through laminate, and product-specific questions about dynamic QR codes and tracking.',
|
||||
'Quick answers: do QR codes expire? Do they work through laminate? What\'s the difference between static and dynamic? Get straight answers before you start creating.',
|
||||
160
|
||||
);
|
||||
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema, softwareApplicationSchema, reviewSchema, aggregateRatingSchema } from '@/lib/schema';
|
||||
import { getFeaturedTestimonials, getAggregateRating } from '@/lib/testimonial-data';
|
||||
import {
|
||||
organizationSchema,
|
||||
websiteSchema,
|
||||
softwareApplicationSchema,
|
||||
reviewSchema,
|
||||
aggregateRatingSchema,
|
||||
} from '@/lib/schema';
|
||||
import {
|
||||
getFeaturedTestimonials,
|
||||
getAggregateRating,
|
||||
} from '@/lib/testimonial-data';
|
||||
import HomePageClient from '@/components/marketing/HomePageClient';
|
||||
|
||||
function truncateAtWord(text: string, maxLength: number): string {
|
||||
@@ -13,16 +22,26 @@ function truncateAtWord(text: string, maxLength: number): string {
|
||||
}
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const title = truncateAtWord('QR Master: Dynamic QR Generator', 60);
|
||||
const title = truncateAtWord('QR Master - Free QR Code Generator', 60);
|
||||
const description = truncateAtWord(
|
||||
'Create dynamic QR codes, track scans, and scale campaigns with secure analytics. Free advanced features, bulk generation, and custom branding available.',
|
||||
'QR Master is a free QR code generator for dynamic QR codes, scan tracking, custom branding, bulk creation, and static QR tools.',
|
||||
160
|
||||
);
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
keywords: ['qr generator', 'free qr code generator', 'custom qr code generator', 'qr code maker', 'online qr code generator', 'dynamic qr code', 'qr code with logo'],
|
||||
keywords: [
|
||||
'qr generator',
|
||||
'free qr code generator',
|
||||
'custom qr code generator',
|
||||
'qr code maker',
|
||||
'online qr code generator',
|
||||
'dynamic qr code',
|
||||
'qr code with logo',
|
||||
'barcode generator',
|
||||
'free barcode generator',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/',
|
||||
languages: {
|
||||
@@ -55,35 +74,49 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
export default function HomePage() {
|
||||
const featuredTestimonials = getFeaturedTestimonials();
|
||||
const aggregateRating = getAggregateRating();
|
||||
const reviewSchemas = featuredTestimonials.map(t => reviewSchema(t));
|
||||
const reviewSchemas = featuredTestimonials.map((t) => reviewSchema(t));
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
websiteSchema(),
|
||||
organizationSchema(),
|
||||
softwareApplicationSchema(aggregateRating),
|
||||
aggregateRatingSchema(aggregateRating),
|
||||
...reviewSchemas
|
||||
]} />
|
||||
...reviewSchemas,
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Server-rendered SEO content for crawlers */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
|
||||
<p>
|
||||
Create professional QR codes for your business with QR Master. Our dynamic QR code generator
|
||||
lets you create trackable QR codes, edit destinations anytime, and view detailed analytics.
|
||||
Perfect for restaurants, retail, events, and marketing campaigns.
|
||||
Create professional QR codes for your business with QR Master. Our
|
||||
dynamic QR code generator lets you create trackable QR codes, edit
|
||||
destinations anytime, and view detailed analytics. Perfect for
|
||||
restaurants, retail, events, and marketing campaigns.
|
||||
</p>
|
||||
<p>
|
||||
Features include: Dynamic QR codes with real-time tracking, bulk QR code generation from Excel/CSV,
|
||||
custom branding with colors and logos, advanced scan analytics showing device types and locations,
|
||||
vCard QR codes for digital business cards, restaurant menu QR codes, and a free{' '}
|
||||
<a href="/tools/barcode-generator">barcode generator</a> for EAN-13, UPC-A, and Code 128 barcodes.
|
||||
Features include: Dynamic QR codes with real-time tracking, bulk QR
|
||||
code generation from Excel/CSV, custom branding with colors and logos,
|
||||
advanced scan analytics showing device types and locations, vCard QR
|
||||
codes for digital business cards, restaurant menu QR codes, and a free{' '}
|
||||
<a href="/tools/barcode-generator">barcode generator</a> for EAN-13,
|
||||
UPC-A, and Code 128 barcodes.
|
||||
</p>
|
||||
<p>
|
||||
Start free with 3 active dynamic QR codes and unlimited static codes. Upgrade to Pro for 50 codes
|
||||
with advanced analytics, or Business for 500 codes with bulk creation and priority support.
|
||||
Popular QR Master workflows include the{' '}
|
||||
<a href="/dynamic-qr-code-generator">
|
||||
free dynamic QR code generator
|
||||
</a>
|
||||
, <a href="/qr-code-tracking">QR code tracking</a>, and the{' '}
|
||||
<a href="/custom-qr-code-generator">custom QR code generator</a> for
|
||||
branded print campaigns.
|
||||
</p>
|
||||
<p>
|
||||
Start free with 3 active dynamic QR codes and unlimited static codes.
|
||||
Upgrade to Pro for 50 codes with advanced analytics, or Business for
|
||||
500 codes with bulk creation and priority support.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,14 +8,17 @@ import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { AnswerFirstBlock } from '@/components/marketing/AnswerFirstBlock';
|
||||
import { FAQSection } from '@/components/aeo/FAQSection';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { MarketingPageTracker, TrackedCtaLink } from '@/components/marketing/MarketingAnalytics';
|
||||
import {
|
||||
MarketingPageTracker,
|
||||
TrackedCtaLink,
|
||||
} from '@/components/marketing/MarketingAnalytics';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free QR Code Tracking & Analytics – Track Every Scan',
|
||||
absolute: 'QR Code Tracking - Track QR Code Scans Free',
|
||||
},
|
||||
description:
|
||||
'Track QR code scans for free. See time, device, and location data for every scan. Use dynamic QR codes to measure printed campaigns and placements from one dashboard.',
|
||||
'Track QR code scans for free with QR code tracking and analytics. See time, device, and location context for printed campaigns and dynamic QR codes.',
|
||||
keywords:
|
||||
'qr code tracking, qr code analytics, track qr scans, dynamic qr tracking, qr scan analytics',
|
||||
alternates: {
|
||||
@@ -26,7 +29,7 @@ export const metadata: Metadata = {
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free QR Code Tracking & Analytics – Track Every Scan',
|
||||
title: 'QR Code Tracking - Track QR Code Scans Free',
|
||||
description:
|
||||
'Track QR code scans with analytics for time, device, and location context. Use dynamic QR codes to measure placements and campaigns.',
|
||||
url: 'https://www.qrmaster.net/qr-code-tracking',
|
||||
@@ -78,25 +81,41 @@ const trackingUseCases = [
|
||||
title: 'Marketing campaigns',
|
||||
description:
|
||||
'Measure how printed placements such as flyers, signs, packaging inserts, or booth materials perform over time.',
|
||||
benefits: ['Compare placements', 'Review campaign timing', 'See scan context in one dashboard'],
|
||||
benefits: [
|
||||
'Compare placements',
|
||||
'Review campaign timing',
|
||||
'See scan context in one dashboard',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Events',
|
||||
description:
|
||||
'Track which event materials drive scans before, during, and after the event instead of treating every print touchpoint the same.',
|
||||
benefits: ['Compare booth and signage scans', 'Watch event-day traffic', 'Keep destinations updateable'],
|
||||
benefits: [
|
||||
'Compare booth and signage scans',
|
||||
'Watch event-day traffic',
|
||||
'Keep destinations updateable',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Product and packaging',
|
||||
description:
|
||||
'Measure which labels, inserts, or support links are getting scans after products leave the warehouse.',
|
||||
benefits: ['Track support content usage', 'Compare packaging placements', 'Keep links current'],
|
||||
benefits: [
|
||||
'Track support content usage',
|
||||
'Compare packaging placements',
|
||||
'Keep links current',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Restaurant and in-store surfaces',
|
||||
description:
|
||||
'Review scans from menus, table cards, windows, or counters and compare when in-store prompts actually get used.',
|
||||
benefits: ['Spot peak scan periods', 'Compare service surfaces', 'Keep menu links current'],
|
||||
benefits: [
|
||||
'Spot peak scan periods',
|
||||
'Compare service surfaces',
|
||||
'Keep menu links current',
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -104,7 +123,11 @@ const trackingComparison = [
|
||||
{ feature: 'Destination can change later', static: false, dynamic: true },
|
||||
{ feature: 'Scan analytics', static: false, dynamic: true },
|
||||
{ feature: 'Placement comparison after print', static: false, dynamic: true },
|
||||
{ feature: 'Reusable for campaigns that evolve', static: false, dynamic: true },
|
||||
{
|
||||
feature: 'Reusable for campaigns that evolve',
|
||||
static: false,
|
||||
dynamic: true,
|
||||
},
|
||||
];
|
||||
|
||||
const faqItems = [
|
||||
@@ -170,13 +193,14 @@ const howToSchema = {
|
||||
'@id': 'https://www.qrmaster.net/qr-code-tracking#howto',
|
||||
name: 'How to track QR code scans',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2025-06-01',
|
||||
dateModified: '2026-05-10',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
description: 'Create a dynamic QR code, deploy it, and review scan analytics from the QR Master dashboard.',
|
||||
description:
|
||||
'Create a dynamic QR code, deploy it, and review scan analytics from the QR Master dashboard.',
|
||||
totalTime: 'PT5M',
|
||||
step: [
|
||||
{
|
||||
@@ -274,7 +298,14 @@ const relatedUseCaseLinks = [
|
||||
export default function QRCodeTrackingPage() {
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
softwareSchema,
|
||||
howToSchema,
|
||||
faqSchema,
|
||||
breadcrumbSchema(breadcrumbItems),
|
||||
]}
|
||||
/>
|
||||
<MarketingPageTracker pageType="commercial" cluster="qr-tracking" />
|
||||
<div className="min-h-screen bg-white">
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-blue-50 via-white to-purple-50 py-20">
|
||||
@@ -288,11 +319,12 @@ export default function QRCodeTrackingPage() {
|
||||
|
||||
<div className="space-y-5">
|
||||
<h1 className="text-5xl font-bold leading-tight text-gray-900 lg:text-6xl">
|
||||
Track every QR code scan with useful context
|
||||
QR Code Tracking for Every Scan
|
||||
</h1>
|
||||
<p className="text-xl leading-relaxed text-gray-600">
|
||||
Use dynamic QR codes to measure scans by time, device, and location context,
|
||||
so printed campaigns and physical placements stop being guesswork.
|
||||
Track QR code scans by time, device, and location context
|
||||
with dynamic QR codes, so printed campaigns and physical
|
||||
placements stop being guesswork.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -305,7 +337,11 @@ export default function QRCodeTrackingPage() {
|
||||
].map((feature) => (
|
||||
<div key={feature} className="flex items-center gap-3">
|
||||
<div className="flex h-5 w-5 items-center justify-center rounded-full bg-green-500">
|
||||
<svg className="h-3 w-3 text-white" fill="currentColor" viewBox="0 0 20 20">
|
||||
<svg
|
||||
className="h-3 w-3 text-white"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
@@ -326,7 +362,10 @@ export default function QRCodeTrackingPage() {
|
||||
pageType="commercial"
|
||||
cluster="qr-tracking"
|
||||
>
|
||||
<Button size="lg" className="w-full px-8 py-4 text-lg sm:w-auto">
|
||||
<Button
|
||||
size="lg"
|
||||
className="w-full px-8 py-4 text-lg sm:w-auto"
|
||||
>
|
||||
Start Tracking Free
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
@@ -337,7 +376,11 @@ export default function QRCodeTrackingPage() {
|
||||
pageType="commercial"
|
||||
cluster="qr-tracking"
|
||||
>
|
||||
<Button variant="outline" size="lg" className="w-full px-8 py-4 text-lg sm:w-auto">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="w-full px-8 py-4 text-lg sm:w-auto"
|
||||
>
|
||||
Create Dynamic QR Code
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
@@ -346,23 +389,33 @@ export default function QRCodeTrackingPage() {
|
||||
|
||||
<div className="relative">
|
||||
<Card className="p-6 shadow-2xl">
|
||||
<h3 className="mb-4 text-lg font-semibold">Analytics overview</h3>
|
||||
<h3 className="mb-4 text-lg font-semibold">
|
||||
Analytics overview
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between border-b pb-3">
|
||||
<span className="text-gray-600">Placement view</span>
|
||||
<span className="font-semibold text-primary-600">Flyer, sign, menu, package</span>
|
||||
<span className="font-semibold text-primary-600">
|
||||
Flyer, sign, menu, package
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-b pb-3">
|
||||
<span className="text-gray-600">Time trend</span>
|
||||
<span className="font-semibold text-primary-600">Hourly and daily patterns</span>
|
||||
<span className="font-semibold text-primary-600">
|
||||
Hourly and daily patterns
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-b pb-3">
|
||||
<span className="text-gray-600">Location context</span>
|
||||
<span className="font-semibold">Country, city, region</span>
|
||||
<span className="font-semibold">
|
||||
Country, city, region
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-gray-600">Device mix</span>
|
||||
<span className="font-semibold">Phone or desktop traffic</span>
|
||||
<span className="font-semibold">
|
||||
Phone or desktop traffic
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -376,7 +429,7 @@ export default function QRCodeTrackingPage() {
|
||||
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<AnswerFirstBlock
|
||||
whatIsIt="QR code tracking works when a dynamic QR code routes the scan through QR Master before the scanner reaches the final destination. That redirect step is what makes analytics such as time, device, and location context possible."
|
||||
whatIsIt="QR code tracking works when a dynamic QR code routes the scan through QR Master before the scanner reaches the final destination. That redirect step makes QR scan analytics such as time, device, location context, total scans, and unique scans possible."
|
||||
whenToUse={[
|
||||
'You want to compare placements such as flyers, signs, menus, packaging, or event surfaces',
|
||||
'You need a measurable record of scans instead of relying on guesswork after print is deployed',
|
||||
@@ -386,9 +439,17 @@ export default function QRCodeTrackingPage() {
|
||||
leftTitle: 'Static QR only',
|
||||
rightTitle: 'Dynamic QR with tracking',
|
||||
items: [
|
||||
{ label: 'Destination can change later', value: true, text: 'Not available' },
|
||||
{
|
||||
label: 'Destination can change later',
|
||||
value: true,
|
||||
text: 'Not available',
|
||||
},
|
||||
{ label: 'Scan analytics', value: true, text: 'Not available' },
|
||||
{ label: 'Placement comparison after print', value: true, text: 'Limited' },
|
||||
{
|
||||
label: 'Placement comparison after print',
|
||||
value: true,
|
||||
text: 'Limited',
|
||||
},
|
||||
],
|
||||
}}
|
||||
howTo={{
|
||||
@@ -401,6 +462,56 @@ export default function QRCodeTrackingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto max-w-6xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-10 max-w-3xl">
|
||||
<p className="mb-3 text-sm font-semibold uppercase tracking-wider text-blue-600">
|
||||
Scan analytics workflow
|
||||
</p>
|
||||
<h2 className="mb-4 text-3xl font-bold text-gray-900">
|
||||
How to track QR code scans from print campaigns
|
||||
</h2>
|
||||
<p className="text-lg leading-relaxed text-gray-600">
|
||||
Create a dynamic QR code for each placement you want to measure,
|
||||
label it by channel or surface, then compare scan activity from
|
||||
the dashboard. This gives each flyer, sign, menu, package
|
||||
insert, or event material its own measurable scan record.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-3">
|
||||
<Card className="p-6">
|
||||
<h3 className="mb-2 text-xl font-semibold text-gray-900">
|
||||
1. Create trackable codes
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Use a dynamic QR code for each important placement so scans
|
||||
route through QR Master before visitors reach the final page.
|
||||
</p>
|
||||
</Card>
|
||||
<Card className="p-6">
|
||||
<h3 className="mb-2 text-xl font-semibold text-gray-900">
|
||||
2. Label each placement
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Name codes by campaign, surface, location, or print batch so
|
||||
the analytics stay useful when traffic starts coming in.
|
||||
</p>
|
||||
</Card>
|
||||
<Card className="p-6">
|
||||
<h3 className="mb-2 text-xl font-semibold text-gray-900">
|
||||
3. Compare scan results
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Review total scans, unique scans, devices, time patterns, and
|
||||
location context to decide which printed placements deserve
|
||||
more budget.
|
||||
</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="container mx-auto max-w-5xl px-4 pb-8 sm:px-6 lg:px-8">
|
||||
<FAQSection items={faqItems} title="QR tracking questions" />
|
||||
</div>
|
||||
@@ -408,16 +519,24 @@ export default function QRCodeTrackingPage() {
|
||||
<section className="bg-gray-50 py-20">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-16 text-center">
|
||||
<h2 className="mb-4 text-4xl font-bold text-gray-900">What QR tracking helps you measure</h2>
|
||||
<h2 className="mb-4 text-4xl font-bold text-gray-900">
|
||||
What QR tracking helps you measure
|
||||
</h2>
|
||||
<p className="mx-auto max-w-3xl text-xl text-gray-600">
|
||||
These are the analytics surfaces the current product experience already supports without inventing extra claims.
|
||||
These are the analytics surfaces the current product experience
|
||||
already supports without inventing extra claims.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||
{trackingFeatures.map((feature) => (
|
||||
<Card key={feature.title} className="p-6 transition-shadow hover:shadow-lg">
|
||||
<h3 className="mb-2 text-xl font-semibold text-gray-900">{feature.title}</h3>
|
||||
<Card
|
||||
key={feature.title}
|
||||
className="p-6 transition-shadow hover:shadow-lg"
|
||||
>
|
||||
<h3 className="mb-2 text-xl font-semibold text-gray-900">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-gray-600">{feature.description}</p>
|
||||
</Card>
|
||||
))}
|
||||
@@ -428,9 +547,12 @@ export default function QRCodeTrackingPage() {
|
||||
<section className="py-20">
|
||||
<div className="container mx-auto max-w-5xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-16 text-center">
|
||||
<h2 className="mb-4 text-4xl font-bold text-gray-900">Tracking setup comparison</h2>
|
||||
<h2 className="mb-4 text-4xl font-bold text-gray-900">
|
||||
Tracking setup comparison
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600">
|
||||
Tracking is a dynamic QR workflow, not a static QR workflow with retroactive reporting.
|
||||
Tracking is a dynamic QR workflow, not a static QR workflow with
|
||||
retroactive reporting.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -438,16 +560,26 @@ export default function QRCodeTrackingPage() {
|
||||
<table className="w-full">
|
||||
<thead className="bg-gray-100">
|
||||
<tr>
|
||||
<th className="px-6 py-4 text-left font-semibold text-gray-900">Capability</th>
|
||||
<th className="px-6 py-4 text-center font-semibold text-gray-900">Static QR</th>
|
||||
<th className="px-6 py-4 text-center font-semibold text-primary-600">Dynamic QR tracking</th>
|
||||
<th className="px-6 py-4 text-left font-semibold text-gray-900">
|
||||
Capability
|
||||
</th>
|
||||
<th className="px-6 py-4 text-center font-semibold text-gray-900">
|
||||
Static QR
|
||||
</th>
|
||||
<th className="px-6 py-4 text-center font-semibold text-primary-600">
|
||||
Dynamic QR tracking
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200">
|
||||
{trackingComparison.map((row) => (
|
||||
<tr key={row.feature}>
|
||||
<td className="px-6 py-4 font-medium text-gray-900">{row.feature}</td>
|
||||
<td className="px-6 py-4 text-center text-gray-600">{row.static ? 'Yes' : 'No'}</td>
|
||||
<td className="px-6 py-4 font-medium text-gray-900">
|
||||
{row.feature}
|
||||
</td>
|
||||
<td className="px-6 py-4 text-center text-gray-600">
|
||||
{row.static ? 'Yes' : 'No'}
|
||||
</td>
|
||||
<td className="px-6 py-4 text-center font-semibold text-primary-600">
|
||||
{row.dynamic ? 'Yes' : 'No'}
|
||||
</td>
|
||||
@@ -462,21 +594,30 @@ export default function QRCodeTrackingPage() {
|
||||
<section className="bg-gray-50 py-20">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-16 text-center">
|
||||
<h2 className="mb-4 text-4xl font-bold text-gray-900">Where tracking is most useful</h2>
|
||||
<h2 className="mb-4 text-4xl font-bold text-gray-900">
|
||||
Where tracking is most useful
|
||||
</h2>
|
||||
<p className="mx-auto max-w-3xl text-xl text-gray-600">
|
||||
Use tracking where physical surfaces or campaigns need measurable follow-through after they are deployed.
|
||||
Use tracking where physical surfaces or campaigns need
|
||||
measurable follow-through after they are deployed.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-8 md:grid-cols-2">
|
||||
{trackingUseCases.map((useCase) => (
|
||||
<Card key={useCase.title} className="p-8">
|
||||
<h3 className="mb-3 text-2xl font-bold text-gray-900">{useCase.title}</h3>
|
||||
<h3 className="mb-3 text-2xl font-bold text-gray-900">
|
||||
{useCase.title}
|
||||
</h3>
|
||||
<p className="mb-6 text-gray-600">{useCase.description}</p>
|
||||
<ul className="space-y-2">
|
||||
{useCase.benefits.map((benefit) => (
|
||||
<li key={benefit} className="flex items-center gap-2">
|
||||
<svg className="h-5 w-5 flex-shrink-0 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<svg
|
||||
className="h-5 w-5 flex-shrink-0 text-green-500"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
@@ -497,40 +638,84 @@ export default function QRCodeTrackingPage() {
|
||||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<svg className="w-5 h-5 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" /></svg>
|
||||
<span className="text-sm font-semibold text-emerald-600 uppercase tracking-wider">Research-backed impact</span>
|
||||
<svg
|
||||
className="w-5 h-5 text-emerald-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-sm font-semibold text-emerald-600 uppercase tracking-wider">
|
||||
Research-backed impact
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
||||
Why Tracking Makes QR Codes Measurable Marketing Assets
|
||||
</h2>
|
||||
<p className="text-gray-600 mb-10 max-w-2xl">
|
||||
Without scan analytics, a printed QR code is invisible — you can't tell if your campaign placement is working. Tracking turns every scan into actionable data.
|
||||
Without scan analytics, a printed QR code is invisible — you can't
|
||||
tell if your campaign placement is working. Tracking turns every
|
||||
scan into actionable data.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-8">
|
||||
<div className="bg-emerald-50 border border-emerald-100 rounded-2xl p-6">
|
||||
<div className="text-4xl font-extrabold text-emerald-600 mb-2">89% vs 33%</div>
|
||||
<div className="text-4xl font-extrabold text-emerald-600 mb-2">
|
||||
89% vs 33%
|
||||
</div>
|
||||
<p className="text-gray-700 text-sm leading-relaxed mb-3">
|
||||
Companies with strong omnichannel engagement — requiring closed-loop tracking from offline to online — retain <strong>89% of their customers</strong>, compared to 33% for businesses without integrated tracking.
|
||||
Companies with strong omnichannel engagement — requiring
|
||||
closed-loop tracking from offline to online — retain{' '}
|
||||
<strong>89% of their customers</strong>, compared to 33% for
|
||||
businesses without integrated tracking.
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
Source: <a href="https://www.aberdeengroup.com/" target="_blank" rel="noopener noreferrer" className="underline hover:text-gray-700">Aberdeen Group</a> — Omnichannel Customer Engagement Study
|
||||
Source:{' '}
|
||||
<a
|
||||
href="https://www.aberdeengroup.com/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline hover:text-gray-700"
|
||||
>
|
||||
Aberdeen Group
|
||||
</a>{' '}
|
||||
— Omnichannel Customer Engagement Study
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-6">
|
||||
<div className="text-4xl font-extrabold text-blue-600 mb-2">46%</div>
|
||||
<div className="text-4xl font-extrabold text-blue-600 mb-2">
|
||||
46%
|
||||
</div>
|
||||
<p className="text-gray-700 text-sm leading-relaxed mb-3">
|
||||
of small businesses identify print and direct mail errors as a major source of wasted marketing budget. QR tracking reveals which placements actually drive scans — so you reprint only what works.
|
||||
of small businesses identify print and direct mail errors as a
|
||||
major source of wasted marketing budget. QR tracking reveals
|
||||
which placements actually drive scans — so you reprint only
|
||||
what works.
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
Source: <a href="https://thedma.org/" target="_blank" rel="noopener noreferrer" className="underline hover:text-gray-700">Data & Marketing Association (DMA)</a>
|
||||
Source:{' '}
|
||||
<a
|
||||
href="https://thedma.org/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline hover:text-gray-700"
|
||||
>
|
||||
Data & Marketing Association (DMA)
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-gray-400 italic">
|
||||
By Timo Knuth, QR Master · Last updated: June 2025 · Based on independent academic and industry research
|
||||
By Timo Knuth, QR Master - Last updated: May 2026 - Based on
|
||||
independent academic and industry research
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -546,9 +731,12 @@ export default function QRCodeTrackingPage() {
|
||||
|
||||
<section className="bg-gradient-to-r from-primary-600 to-purple-600 py-20 text-white">
|
||||
<div className="container mx-auto max-w-4xl px-4 text-center sm:px-6 lg:px-8">
|
||||
<h2 className="mb-6 text-4xl font-bold">Start tracking your QR codes today</h2>
|
||||
<h2 className="mb-6 text-4xl font-bold">
|
||||
Start tracking your QR codes today
|
||||
</h2>
|
||||
<p className="mb-8 text-xl text-primary-100">
|
||||
Measure scans with enough context to improve the next placement, campaign, or printed workflow.
|
||||
Measure scans with enough context to improve the next placement,
|
||||
campaign, or printed workflow.
|
||||
</p>
|
||||
<div className="flex flex-col justify-center gap-4 sm:flex-row">
|
||||
<TrackedCtaLink
|
||||
|
||||
@@ -18,7 +18,7 @@ export function BarcodeGuide() {
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-xs text-slate-400 mb-8 not-prose">
|
||||
By <strong className="text-slate-600">Timo Knuth</strong>, QR Master · Last updated: April 2026 · GS1-verified content
|
||||
By <strong className="text-slate-600">Timo Knuth</strong>, QR Master · Last updated: May 2026 · GS1-verified content
|
||||
</p>
|
||||
|
||||
<p className="lead text-xl text-slate-600">
|
||||
|
||||
@@ -1,20 +1,46 @@
|
||||
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import BarcodeGeneratorClient from './BarcodeGeneratorClient';
|
||||
import { BarcodeGuide } from './BarcodeGuide';
|
||||
import { Barcode as BarcodeIcon, Shield, Zap, Printer, Download, Share2, Sparkles, Sliders, Check } from 'lucide-react';
|
||||
import {
|
||||
Barcode as BarcodeIcon,
|
||||
Shield,
|
||||
Zap,
|
||||
Printer,
|
||||
Download,
|
||||
Share2,
|
||||
Sparkles,
|
||||
Sliders,
|
||||
Check,
|
||||
} from 'lucide-react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
import {
|
||||
generateSoftwareAppSchema,
|
||||
generateFaqSchema,
|
||||
} from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free Barcode Generator Online – EAN, UPC, Code 128',
|
||||
absolute: 'Free Custom Barcode Generator - EAN, UPC, Code 128',
|
||||
},
|
||||
description: 'Free online barcode generator for EAN-13, UPC-A, and Code 128 barcodes. Create scannable labels for retail, inventory, and logistics instantly. Download PNG or SVG — no signup required.',
|
||||
keywords: ['barcode generator', 'online barcode maker', 'create barcode free', 'ean-13 generator', 'upc-a generator', 'code 128 generator', 'barcode creator', 'printable barcodes'],
|
||||
description:
|
||||
'Free custom barcode generator and barcode maker for EAN-13, UPC-A, UPC barcode, and Code 128. Create scannable labels for retail and inventory, then download PNG or SVG.',
|
||||
keywords: [
|
||||
'barcode generator',
|
||||
'custom barcode generator',
|
||||
'online barcode generator',
|
||||
'free online barcode generator',
|
||||
'barcode maker',
|
||||
'upc barcode generator',
|
||||
'ean-13 generator',
|
||||
'upc-a generator',
|
||||
'code 128 generator',
|
||||
'barcode creator',
|
||||
'create barcode free',
|
||||
'printable barcodes',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
languages: {
|
||||
@@ -23,18 +49,22 @@ export const metadata: Metadata = {
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Barcode Generator: Create EAN, UPC & Code 128',
|
||||
description: 'Barcode Generator: Create professional labels instantly. Free & Secured.',
|
||||
title: 'Free Custom Barcode Generator - EAN, UPC & Code 128',
|
||||
description:
|
||||
'Free online barcode maker for EAN-13, UPC-A, and Code 128. Create scannable custom barcodes in seconds and download PNG or SVG.',
|
||||
url: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
siteName: 'QR Master',
|
||||
locale: 'en_US',
|
||||
type: 'website',
|
||||
images: [{ url: '/barcode-generator-preview.png', width: 1200, height: 630 }],
|
||||
images: [
|
||||
{ url: '/barcode-generator-preview.png', width: 1200, height: 630 },
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free Barcode Generator',
|
||||
description: 'Create custom barcodes in seconds. Download high-quality PNG/SVG.',
|
||||
description:
|
||||
'Create custom barcodes in seconds. Download high-quality PNG/SVG.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
@@ -55,8 +85,9 @@ const jsonLd = {
|
||||
{
|
||||
'@type': 'WebPage',
|
||||
'@id': 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
name: 'Free Barcode Generator Online – EAN, UPC, Code 128',
|
||||
description: 'A barcode generator converts any number or text into a scannable barcode image for retail labels, inventory, and product packaging. Supports EAN-13, UPC-A, and Code 128.',
|
||||
name: 'Free Custom Barcode Generator Online - EAN, UPC, Code 128',
|
||||
description:
|
||||
'A barcode generator converts any number or text into a scannable barcode image for retail labels, inventory, and product packaging. Supports EAN-13, UPC-A, and Code 128.',
|
||||
speakable: {
|
||||
'@type': 'SpeakableSpecification',
|
||||
cssSelector: ['.bg-blue-50', 'h1'],
|
||||
@@ -66,13 +97,13 @@ const jsonLd = {
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
dateModified: '2026-04-27',
|
||||
dateModified: '2026-05-10',
|
||||
},
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a Barcode',
|
||||
datePublished: '2024-06-01',
|
||||
dateModified: '2026-04-27',
|
||||
dateModified: '2026-05-10',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
@@ -116,35 +147,63 @@ const jsonLd = {
|
||||
generateFaqSchema({
|
||||
'What is a Barcode Generator?': {
|
||||
question: 'What is a Barcode Generator?',
|
||||
answer: 'A Barcode Generator is an online tool that converts numbers or text into scannable barcode images that can be used for products, labels, and inventory systems.',
|
||||
answer:
|
||||
'A Barcode Generator is an online tool that converts numbers or text into scannable barcode images that can be used for products, labels, and inventory systems.',
|
||||
},
|
||||
'Is this barcode generator free to use?': {
|
||||
question: 'Is this barcode generator free to use?',
|
||||
answer: 'Yes, our online barcode generator is completely free to use with no hidden costs or sign-ups required. You can generate, download, and print barcodes instantly.',
|
||||
answer:
|
||||
'Yes, our online barcode generator is completely free to use with no hidden costs or sign-ups required. You can generate, download, and print barcodes instantly.',
|
||||
},
|
||||
'Which barcode format should I use?': {
|
||||
question: 'Which barcode format should I use?',
|
||||
answer: 'EAN-13 is standard for retail in Europe/Global. UPC-A is standard for retail in USA/Canada. Code 128 is best for logistics and internal tracking as it supports letters and numbers.',
|
||||
answer:
|
||||
'EAN-13 is standard for retail in Europe/Global. UPC-A is standard for retail in USA/Canada. Code 128 is best for logistics and internal tracking as it supports letters and numbers.',
|
||||
},
|
||||
'Can I download barcodes in vector format (SVG)?': {
|
||||
question: 'Can I download barcodes in vector format (SVG)?',
|
||||
answer: 'Yes! We offer SVG downloads. SVG files are vector-based, meaning they can be scaled to any size without losing quality—perfect for professional product packaging.',
|
||||
answer:
|
||||
'Yes! We offer SVG downloads. SVG files are vector-based, meaning they can be scaled to any size without losing quality—perfect for professional product packaging.',
|
||||
},
|
||||
'How do I generate a barcode online?': {
|
||||
question: 'How do I generate a barcode online?',
|
||||
answer: 'To generate a barcode online, enter your product number or text, select the desired barcode format (such as EAN-13 or Code 128), and click the generate button. The barcode will be created instantly.',
|
||||
answer:
|
||||
'To generate a barcode online, enter your product number or text, select the desired barcode format (such as EAN-13 or Code 128), and click the generate button. The barcode will be created instantly.',
|
||||
},
|
||||
'Are generated barcodes scannable?': {
|
||||
question: 'Are generated barcodes scannable?',
|
||||
answer: 'Yes, barcodes generated with a proper barcode generator are fully scannable. We generate standard-compliant barcodes readable by any standard optical or laser barcode scanner.',
|
||||
answer:
|
||||
'Yes, barcodes generated with a proper barcode generator are fully scannable. We generate standard-compliant barcodes readable by any standard optical or laser barcode scanner.',
|
||||
},
|
||||
'Can I use these barcodes for Amazon (EAN/UPC)?': {
|
||||
question: 'Can I use these barcodes for Amazon (EAN/UPC)?',
|
||||
answer: 'You can generate the image for Amazon here if you already have your EAN/UPC number. However, you cannot "create" a valid global EAN number here—you must purchase those official numbers from GS1 to sell on major platforms like Amazon.',
|
||||
answer:
|
||||
'You can generate the image for Amazon here if you already have your EAN/UPC number. However, you cannot "create" a valid global EAN number here—you must purchase those official numbers from GS1 to sell on major platforms like Amazon.',
|
||||
},
|
||||
'What is the difference between a barcode and a QR code?': {
|
||||
question: 'What is the difference between a barcode and a QR code?',
|
||||
answer: 'A barcode stores data horizontally (1D) and is mainly used for product IDs. A QR code stores data in 2D (matrix) and can hold much more information, such as URLs, vCards, or WiFi credentials.',
|
||||
answer:
|
||||
'A barcode stores data horizontally (1D) and is mainly used for product IDs. A QR code stores data in 2D (matrix) and can hold much more information, such as URLs, vCards, or WiFi credentials.',
|
||||
},
|
||||
'What barcode format do Amazon and Walmart require?': {
|
||||
question: 'What barcode format do Amazon and Walmart require?',
|
||||
answer:
|
||||
'Amazon and Walmart require UPC-A (12 digits) for products sold in the United States and Canada, and EAN-13 (13 digits) for products sold internationally. You must purchase official GS1-registered numbers to sell on these platforms — you cannot self-generate valid retail UPC/EAN numbers.',
|
||||
},
|
||||
'What is the minimum print size for a scannable barcode?': {
|
||||
question: 'What is the minimum print size for a scannable barcode?',
|
||||
answer:
|
||||
'The GS1 standard recommends a minimum width of 25.9mm (1 inch) for EAN-13 barcodes on retail packaging. Smaller sizes increase scan failure rates. For internal inventory labels, Code 128 can be printed as narrow as 15mm wide while remaining reliably scannable with modern handheld scanners.',
|
||||
},
|
||||
'Can I use Code 128 for inventory management?': {
|
||||
question: 'Can I use Code 128 for inventory management?',
|
||||
answer:
|
||||
'Yes. Code 128 is the most widely used barcode format for inventory, logistics, and warehousing because it supports both letters and numbers, has high data density, and is readable by virtually all laser and 2D scanners. It is the recommended format for internal SKU systems, warehouse bin labels, and shipping labels.',
|
||||
},
|
||||
'What is the difference between EAN-13 and UPC-A?': {
|
||||
question: 'What is the difference between EAN-13 and UPC-A?',
|
||||
answer:
|
||||
'EAN-13 (13 digits) is the international retail standard used in Europe, Asia, and globally. UPC-A (12 digits) is the North American retail standard used in the US and Canada. An EAN-13 barcode starting with a 0 is actually a UPC-A code — all UPC-A codes are a subset of EAN-13. Most modern POS scanners read both formats.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
@@ -157,18 +216,35 @@ export default function BarcodeGeneratorPage() {
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="Barcode Generator" toolSlug="barcode-generator" />
|
||||
<ToolBreadcrumb
|
||||
toolName="Barcode Generator"
|
||||
toolSlug="barcode-generator"
|
||||
/>
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden bg-slate-900">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
{/* Barcode Pattern */}
|
||||
<svg className="w-full h-full" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
className="w-full h-full"
|
||||
width="100%"
|
||||
height="100%"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs>
|
||||
<pattern id="barcode_pattern" 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
|
||||
id="barcode_pattern"
|
||||
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)" />
|
||||
@@ -186,12 +262,19 @@ export default function BarcodeGeneratorPage() {
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
Free Online <span className="text-blue-400">Barcode Generator</span>
|
||||
Free Custom{' '}
|
||||
<span className="text-blue-400">Barcode Generator</span>
|
||||
<span className="block text-2xl md:text-3xl font-semibold text-slate-300 mt-2">
|
||||
Barcode Maker for EAN, UPC & Code 128
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-slate-400 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
A <strong>barcode generator</strong> converts any number or text into a scannable barcode image — ready to download, print, and use on products, labels, or inventory systems.
|
||||
<span className="text-white block sm:inline mt-2 sm:mt-0"> Supports EAN-13, UPC-A, and Code 128. No signup required.</span>
|
||||
A <strong>free custom barcode generator</strong> and{' '}
|
||||
<strong>barcode maker</strong> for EAN-13, UPC-A, UPC barcodes,
|
||||
and Code 128. Convert any number or text into a scannable
|
||||
barcode, download PNG or SVG, print instantly, no signup
|
||||
required.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
@@ -220,19 +303,29 @@ export default function BarcodeGeneratorPage() {
|
||||
<div className="w-full bg-gradient-to-br from-blue-400 to-indigo-600 rounded-xl shadow-lg p-5 mb-6 relative overflow-hidden text-white">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<BarcodeIcon className="w-8 h-8 opacity-80" />
|
||||
<div className="bg-white/20 px-2 py-1 rounded text-xs font-bold uppercase tracking-wider">Label</div>
|
||||
<div className="bg-white/20 px-2 py-1 rounded text-xs font-bold uppercase tracking-wider">
|
||||
Label
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xl font-bold tracking-wider mb-1">
|
||||
PROD-98234
|
||||
</div>
|
||||
<div className="text-xl font-bold tracking-wider mb-1">PROD-98234</div>
|
||||
<div className="text-xs opacity-70">Inventory ID</div>
|
||||
</div>
|
||||
|
||||
<div className="w-48 h-32 bg-white rounded-xl p-4 shadow-inner relative overflow-hidden flex flex-col items-center justify-center">
|
||||
<div className="w-full h-16 bg-black flex gap-1 mb-2">
|
||||
{[2, 4, 1, 3, 2, 1, 4, 2, 1, 3].map((w, i) => (
|
||||
<div key={i} className="bg-black flex-1" style={{ flex: w }} />
|
||||
<div
|
||||
key={i}
|
||||
className="bg-black flex-1"
|
||||
style={{ flex: w }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-[10px] font-mono font-bold tracking-widest uppercase">98234001A</div>
|
||||
<div className="text-[10px] font-mono font-bold tracking-widest uppercase">
|
||||
98234001A
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
@@ -241,8 +334,12 @@ export default function BarcodeGeneratorPage() {
|
||||
<Printer className="w-5 h-5 text-blue-500" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Ready</div>
|
||||
<div className="text-sm font-bold text-white">Print Instantly</div>
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">
|
||||
Ready
|
||||
</div>
|
||||
<div className="text-sm font-bold text-white">
|
||||
Print Instantly
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -259,33 +356,62 @@ export default function BarcodeGeneratorPage() {
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 bg-white border-b border-slate-100">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="bg-blue-50 border-l-4 border-blue-500 rounded-xl p-6 mb-8">
|
||||
<h2 className="text-xl font-bold text-slate-900 mb-2">What is a Barcode Generator?</h2>
|
||||
<h2 className="text-xl font-bold text-slate-900 mb-2">
|
||||
What is a Barcode Generator?
|
||||
</h2>
|
||||
<p className="text-slate-700 leading-relaxed">
|
||||
A <strong>barcode generator</strong> is an online tool that converts a number or text string into a scannable barcode image (EAN-13, UPC-A, or Code 128). The generated barcode can be downloaded as PNG or SVG and printed on product labels, packaging, or inventory stickers for use with any standard barcode scanner.
|
||||
A <strong>custom barcode generator</strong> is an online tool
|
||||
that converts a number or text string into a scannable barcode
|
||||
image (EAN-13, UPC-A, or Code 128). The generated barcode can be
|
||||
downloaded as PNG or SVG and printed on product labels,
|
||||
packaging, or inventory stickers for use with any standard
|
||||
barcode scanner.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-8">
|
||||
<div className="text-center p-5 rounded-xl bg-slate-50 border border-slate-200">
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-1">EAN-13</div>
|
||||
<div className="text-sm font-semibold text-slate-700 mb-1">Global Retail Standard</div>
|
||||
<div className="text-xs text-slate-500">Used on over 5 billion product labels worldwide (GS1, 2024)</div>
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-1">
|
||||
EAN-13
|
||||
</div>
|
||||
<div className="text-sm font-semibold text-slate-700 mb-1">
|
||||
Global Retail Standard
|
||||
</div>
|
||||
<div className="text-xs text-slate-500">
|
||||
Used on over 5 billion product labels worldwide (GS1, 2024)
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center p-5 rounded-xl bg-slate-50 border border-slate-200">
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-1">UPC-A</div>
|
||||
<div className="text-sm font-semibold text-slate-700 mb-1">North America Standard</div>
|
||||
<div className="text-xs text-slate-500">Required by Amazon, Walmart, Target for product listings</div>
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-1">
|
||||
UPC-A
|
||||
</div>
|
||||
<div className="text-sm font-semibold text-slate-700 mb-1">
|
||||
North America Standard
|
||||
</div>
|
||||
<div className="text-xs text-slate-500">
|
||||
Required by Amazon, Walmart, Target for product listings
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center p-5 rounded-xl bg-slate-50 border border-slate-200">
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-1">Code 128</div>
|
||||
<div className="text-sm font-semibold text-slate-700 mb-1">Inventory & Logistics</div>
|
||||
<div className="text-xs text-slate-500">Supports letters + numbers — best for internal SKU systems</div>
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-1">
|
||||
Code 128
|
||||
</div>
|
||||
<div className="text-sm font-semibold text-slate-700 mb-1">
|
||||
Inventory & Logistics
|
||||
</div>
|
||||
<div className="text-xs text-slate-500">
|
||||
Supports letters + numbers — best for internal SKU systems
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-amber-50 border border-amber-200 rounded-xl p-5">
|
||||
<h3 className="font-bold text-slate-900 mb-2">Barcode vs. QR Code — When to Use Which</h3>
|
||||
<h3 className="font-bold text-slate-900 mb-2">
|
||||
Barcode vs. QR Code — When to Use Which
|
||||
</h3>
|
||||
<div className="grid md:grid-cols-2 gap-4 text-sm text-slate-700">
|
||||
<div>
|
||||
<p className="font-semibold text-slate-800 mb-1">✓ Use a barcode for:</p>
|
||||
<p className="font-semibold text-slate-800 mb-1">
|
||||
✓ Use a barcode for:
|
||||
</p>
|
||||
<ul className="space-y-1 list-disc list-inside text-slate-600">
|
||||
<li>Product SKUs and retail checkout</li>
|
||||
<li>Warehouse shelf and bin labels</li>
|
||||
@@ -294,7 +420,9 @@ export default function BarcodeGeneratorPage() {
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-semibold text-slate-800 mb-1">✓ Use a QR code for:</p>
|
||||
<p className="font-semibold text-slate-800 mb-1">
|
||||
✓ Use a QR code for:
|
||||
</p>
|
||||
<ul className="space-y-1 list-disc list-inside text-slate-600">
|
||||
<li>Restaurant menus and digital content</li>
|
||||
<li>Marketing campaigns and landing pages</li>
|
||||
@@ -368,15 +496,78 @@ export default function BarcodeGeneratorPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-slate-50 border-y border-slate-200">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<div className="max-w-3xl mb-10">
|
||||
<p className="text-sm font-semibold text-blue-600 uppercase tracking-wider mb-3">
|
||||
Custom barcode generator
|
||||
</p>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-4">
|
||||
Create custom barcodes for labels, inventory, and product
|
||||
workflows
|
||||
</h2>
|
||||
<p className="text-lg text-slate-600 leading-relaxed">
|
||||
Use the barcode maker when you already have a product number,
|
||||
SKU, inventory ID, or internal reference and need a printable
|
||||
barcode image. Choose the format, adjust the dimensions, show or
|
||||
hide the text value, then export a clean PNG or SVG for labels.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<article className="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h3 className="font-bold text-slate-900 mb-2">Retail labels</h3>
|
||||
<p className="text-slate-600 text-sm leading-relaxed">
|
||||
Generate EAN-13 or UPC-A barcode images for packaging and
|
||||
shelf labels when you already have valid GS1-issued numbers.
|
||||
</p>
|
||||
</article>
|
||||
<article className="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h3 className="font-bold text-slate-900 mb-2">
|
||||
Inventory codes
|
||||
</h3>
|
||||
<p className="text-slate-600 text-sm leading-relaxed">
|
||||
Use Code 128 for alphanumeric SKUs, warehouse bins, assets,
|
||||
and internal tracking labels that need scanner-friendly codes.
|
||||
</p>
|
||||
</article>
|
||||
<article className="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h3 className="font-bold text-slate-900 mb-2">
|
||||
Printable exports
|
||||
</h3>
|
||||
<p className="text-slate-600 text-sm leading-relaxed">
|
||||
Download SVG for crisp print layouts or PNG for fast use in
|
||||
docs, product sheets, and simple label workflows.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<p className="mt-8 text-sm text-slate-600">
|
||||
Need a code for a web page instead of a retail scanner? Use the{' '}
|
||||
<a
|
||||
href="/dynamic-qr-code-generator"
|
||||
className="font-semibold text-blue-700 underline"
|
||||
>
|
||||
dynamic QR code generator
|
||||
</a>{' '}
|
||||
if the destination may change later, or the{' '}
|
||||
<a
|
||||
href="/qr-code-tracking"
|
||||
className="font-semibold text-blue-700 underline"
|
||||
>
|
||||
QR code tracking
|
||||
</a>{' '}
|
||||
workflow when you need scan analytics.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* RELATED TOOLS */}
|
||||
<RelatedTools />
|
||||
|
||||
{/* SEO GUIDE */}
|
||||
<BarcodeGuide />
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,13 +4,15 @@ import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Free QR Code Tools | URL, vCard, WiFi & More | QR Master',
|
||||
description: 'Access our complete collection of free QR code generators. Create codes for URLs, WiFi, plain text, vCards, and more. No signup required for static codes.',
|
||||
description:
|
||||
'Access free QR code tools for URLs, WiFi, vCards, barcodes, and more. Use QR Master for static codes, dynamic QR codes, and QR code tracking.',
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free QR Code Tools Collection',
|
||||
description: 'All your QR code needs in one place. Free forever static codes.',
|
||||
description:
|
||||
'All your QR code needs in one place. Free forever static codes.',
|
||||
url: 'https://www.qrmaster.net/tools',
|
||||
siteName: 'QR Master',
|
||||
type: 'website',
|
||||
@@ -29,7 +31,8 @@ export default function ToolsHubPage() {
|
||||
Free QR Code Tools
|
||||
</h1>
|
||||
<p className="text-xl text-slate-600 mb-8 leading-relaxed max-w-2xl mx-auto">
|
||||
Generate static QR codes for any purpose. No credit card, no expiration, no hidden fees.
|
||||
Generate static QR codes for any purpose. No credit card, no
|
||||
expiration, no hidden fees.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -40,11 +43,28 @@ export default function ToolsHubPage() {
|
||||
|
||||
<section className="py-20 px-4">
|
||||
<div className="container mx-auto max-w-3xl text-center">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-4">Why are these tools free?</h2>
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-4">
|
||||
Why are these tools free?
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-8">
|
||||
We believe basic QR codes should be accessible to everyone. Our static QR codes encode your data directly into the image,
|
||||
meaning we don't need to host tracking servers for them. That's why they are free forever.
|
||||
If you need tracking and editability, check out our Dynamic QR Codes.
|
||||
We believe basic QR codes should be accessible to everyone. Our
|
||||
static QR codes encode your data directly into the image, meaning we
|
||||
don't need to host tracking servers for them. That's why they are
|
||||
free forever. If you need tracking and editability, use our{' '}
|
||||
<a
|
||||
href="/dynamic-qr-code-generator"
|
||||
className="font-semibold text-indigo-700 underline"
|
||||
>
|
||||
dynamic QR code generator
|
||||
</a>{' '}
|
||||
or learn how{' '}
|
||||
<a
|
||||
href="/qr-code-tracking"
|
||||
className="font-semibold text-indigo-700 underline"
|
||||
>
|
||||
QR code tracking
|
||||
</a>{' '}
|
||||
works.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -34,14 +34,20 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
// All blog posts
|
||||
// Filter out future posts so Google doesn't see them
|
||||
const blogPages = blogPosts
|
||||
.filter(post => {
|
||||
const publishDate = post.datePublished ? new Date(post.datePublished) : new Date(post.date);
|
||||
.filter((post) => {
|
||||
const publishDate = post.datePublished
|
||||
? new Date(post.datePublished)
|
||||
: new Date(post.date);
|
||||
return publishDate <= new Date();
|
||||
})
|
||||
.map((post) => ({
|
||||
url: `${baseUrl}/blog/${post.slug}`,
|
||||
// Use updatedAt if available, otherwise dateModified or datePublished
|
||||
lastModified: post.updatedAt ? new Date(post.updatedAt) : (post.dateModified ? new Date(post.dateModified) : new Date()),
|
||||
lastModified: post.updatedAt
|
||||
? new Date(post.updatedAt)
|
||||
: post.dateModified
|
||||
? new Date(post.dateModified)
|
||||
: new Date(),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.8,
|
||||
}));
|
||||
@@ -51,7 +57,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
};
|
||||
|
||||
const toolLastModified: Record<string, Date> = {
|
||||
'barcode-generator': new Date('2026-04-27'),
|
||||
'barcode-generator': new Date('2026-05-10'),
|
||||
'vcard-qr-code': new Date('2026-04-27'),
|
||||
'instagram-qr-code': new Date('2026-04-27'),
|
||||
'wifi-qr-code': new Date('2026-04-27'),
|
||||
@@ -60,7 +66,8 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const toolPages = freeTools.map((slug) => ({
|
||||
url: `${baseUrl}/tools/${slug}`,
|
||||
lastModified: toolLastModified[slug] ?? new Date('2026-01-01'),
|
||||
changeFrequency: slug === 'barcode-generator' ? 'weekly' as const : 'monthly' as const,
|
||||
changeFrequency:
|
||||
slug === 'barcode-generator' ? ('weekly' as const) : ('monthly' as const),
|
||||
priority: highPriorityTools[slug] ?? 0.8,
|
||||
}));
|
||||
|
||||
@@ -197,7 +204,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/qr-code-tracking`,
|
||||
lastModified: new Date(),
|
||||
lastModified: new Date('2026-05-10'),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.9,
|
||||
},
|
||||
@@ -215,7 +222,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/dynamic-qr-code-generator`,
|
||||
lastModified: new Date('2026-04-27'),
|
||||
lastModified: new Date('2026-05-10'),
|
||||
changeFrequency: 'weekly',
|
||||
priority: 0.95,
|
||||
},
|
||||
@@ -300,7 +307,6 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
priority: 0.7,
|
||||
},
|
||||
|
||||
|
||||
...toolPages,
|
||||
...blogPages,
|
||||
...learnPages,
|
||||
|
||||
@@ -44,6 +44,7 @@ const TOOLS = [
|
||||
{ icon: Music, name: 'TikTok', description: 'Open TikTok profile', href: '/tools/tiktok-qr-code', color: 'text-slate-900', bg: 'bg-slate-100' },
|
||||
{ icon: MapPin, name: 'Location', description: 'Share GPS coordinates', href: '/tools/location-qr-code', color: 'text-emerald-500', bg: 'bg-emerald-50' },
|
||||
{ icon: Phone, name: 'Call', description: 'Start a phone call', href: '/tools/phone-qr-code', color: 'text-teal-500', bg: 'bg-teal-50' },
|
||||
{ icon: Barcode, name: 'Barcode', description: 'Free online barcode generator', href: '/tools/barcode-generator', color: 'text-amber-600', bg: 'bg-amber-50' },
|
||||
];
|
||||
|
||||
const containerVariants: Variants = {
|
||||
|
||||
@@ -502,9 +502,9 @@ export const blogPosts: BlogPost[] = [
|
||||
|
||||
{
|
||||
slug: "vcard-qr-code-generator",
|
||||
title: "Free vCard QR Generator: Digital Cards",
|
||||
description: "Create professional vCard QR codes for digital business cards. Share contact info instantly with a scan—includes templates and best practices.",
|
||||
excerpt: "Create professional vCard QR codes for digital business cards. Share contact info instantly with a scan—includes templates and best practices.",
|
||||
title: "vCard QR Code: What It Is, How It Works & Best Practices",
|
||||
description: "Everything you need to know about vCard QR codes: how they work, static vs dynamic, what to include, and how to create one free in seconds.",
|
||||
excerpt: "Everything you need to know about vCard QR codes: how they work, static vs dynamic, what to include, and how to create one free in seconds.",
|
||||
category: "Business Cards",
|
||||
pillar: "use-cases",
|
||||
published: true,
|
||||
@@ -541,12 +541,74 @@ export const blogPosts: BlogPost[] = [
|
||||
<div class="post-metadata bg-blue-50 p-4 rounded-lg mb-8 border-l-4 border-blue-500">
|
||||
<p class="text-sm text-gray-700">
|
||||
<strong>Author:</strong> Timo Knuth, QR Code & Marketing Expert<br/>
|
||||
📅 <strong>Published:</strong> January 5, 2026 | <strong>Last updated:</strong> January 26, 2026
|
||||
📅 <strong>Published:</strong> January 5, 2026 | <strong>Last updated:</strong> May 4, 2026
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-xl p-6 mb-8">
|
||||
<p class="text-blue-900 font-semibold mb-2">Ready to create one?</p>
|
||||
<p class="text-blue-800 mb-3">Use the free vCard QR Code Generator — no signup required, works on iPhone and Android.</p>
|
||||
<a href="/tools/vcard-qr-code" class="inline-block bg-blue-600 text-white font-semibold px-5 py-2.5 rounded-lg hover:bg-blue-700 transition-colors">Create your vCard QR Code →</a>
|
||||
</div>
|
||||
|
||||
<h2>What is a vCard QR Code?</h2>
|
||||
<p>A vCard (Virtual Contact File) QR code contains your contact information in a standardized format (.vcf). When someone scans it with their smartphone camera, they can instantly save your details to their contacts—no typing required.</p>
|
||||
<p>A vCard (Virtual Contact File) QR code contains your contact information in a standardized format (.vcf). When someone scans it with their smartphone camera, they can instantly save your details to their contacts — no typing required. It replaces the friction of spelling out a phone number or email at a networking event with a single tap.</p>
|
||||
<p>The QR code encodes a VCF data string directly. That string includes fields like name, phone, email, company, job title, website, and LinkedIn. When the phone's camera reads the code, it parses the VCF and offers to add the contact in one tap.</p>
|
||||
|
||||
<h2>Static vs Dynamic vCard QR Codes</h2>
|
||||
<p>This is the most important choice you'll make.</p>
|
||||
<ul>
|
||||
<li><strong>Static vCard QR codes</strong> embed your contact info directly into the code. They work without any internet connection — the data is in the code itself. The downside: if your phone number or email changes, the code is outdated and needs to be reprinted.</li>
|
||||
<li><strong>Dynamic vCard QR codes</strong> point to a redirect URL that serves the VCF. You can update your contact info at any time from a dashboard — the printed QR code stays the same. Dynamic codes also give you scan analytics: how many times it was scanned, on which devices, from which locations.</li>
|
||||
</ul>
|
||||
<p><strong>Recommendation:</strong> Use dynamic if you might change jobs, switch numbers, or want to track engagement. Use static if you just need a simple one-time contact share.</p>
|
||||
<p>The <a href="/tools/vcard-qr-code" class="text-blue-600 underline">QR Master vCard generator</a> supports both — static for simplicity, dynamic for flexibility and tracking.</p>
|
||||
|
||||
<h2>What to Include in a vCard QR Code</h2>
|
||||
<p>Less is more. Include the fields people actually need to follow up with you:</p>
|
||||
<ul>
|
||||
<li><strong>Full name</strong> — exactly as you want it to appear in contacts</li>
|
||||
<li><strong>Phone number</strong> — in international format (+49...) for cross-border scanning</li>
|
||||
<li><strong>Email address</strong> — your primary professional email</li>
|
||||
<li><strong>Company and job title</strong> — helps recipients remember context</li>
|
||||
<li><strong>Website or LinkedIn</strong> — one link, whichever drives the most value for you</li>
|
||||
</ul>
|
||||
<p>Avoid adding multiple phone numbers or social handles unless you have a specific reason — cluttered vCards confuse the contact save prompt on some phones.</p>
|
||||
|
||||
<h2>How to Create a vCard QR Code (Free)</h2>
|
||||
<ol>
|
||||
<li>Go to the <a href="/tools/vcard-qr-code" class="text-blue-600 underline">free vCard QR Code Generator</a>.</li>
|
||||
<li>Enter your contact details: name, phone, email, company, title, and optionally a website or LinkedIn URL.</li>
|
||||
<li>Choose static (simple) or dynamic (editable + trackable).</li>
|
||||
<li>Customize the design: add your logo or headshot, pick brand colors, and make sure there's strong contrast.</li>
|
||||
<li>Download in SVG for print (scales to any size without pixelation) or PNG for digital use.</li>
|
||||
<li>Test on both iPhone and Android before printing in bulk.</li>
|
||||
</ol>
|
||||
|
||||
<h2>Where to Use a vCard QR Code</h2>
|
||||
<ul>
|
||||
<li><strong>Business cards:</strong> Print the QR on the back. Replaces typing out contact info at events.</li>
|
||||
<li><strong>Email signature:</strong> Embed the QR code image so recipients on mobile can tap to save your contact.</li>
|
||||
<li><strong>Conference badges and lanyards:</strong> Makes networking frictionless — one scan at a booth saves full contact details.</li>
|
||||
<li><strong>Trade show materials:</strong> Brochures, flyers, and rollup banners with a QR code so visitors can save your info without collecting paper.</li>
|
||||
<li><strong>LinkedIn profile:</strong> Share as an image for connections who want to save your contact directly.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<h3>Does a vCard QR code work on iPhone?</h3>
|
||||
<p>Yes. The native iOS camera app reads QR codes and prompts to add the contact directly via the VCF format. No app needed.</p>
|
||||
<h3>Does it work on Android?</h3>
|
||||
<p>Yes. The Google Lens camera and most Android manufacturer camera apps support VCF QR codes natively. The contact save prompt appears automatically after scanning.</p>
|
||||
<h3>Can I include my photo in a vCard QR code?</h3>
|
||||
<p>The VCF format supports embedding a photo, but the encoded QR code becomes very large (and harder to scan) with a full photo. It's better to skip the photo in the vCard itself and put your headshot next to the QR code on the business card instead.</p>
|
||||
<h3>What's the best file format to download?</h3>
|
||||
<p>SVG for print — it scales to any size with no pixelation. PNG at 300 DPI for digital sharing.</p>
|
||||
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-xl p-6 mt-8">
|
||||
<h3 class="font-bold text-gray-900 mt-0 mb-2">Create your vCard QR Code</h3>
|
||||
<p class="text-gray-700 mb-4">Free, no signup required. Download in SVG or PNG. Works on iPhone and Android.</p>
|
||||
<a href="/tools/vcard-qr-code" class="inline-block bg-blue-600 text-white font-semibold px-5 py-2.5 rounded-lg hover:bg-blue-700 transition-colors">Open the free vCard generator →</a>
|
||||
</div>
|
||||
</div>`,
|
||||
},
|
||||
|
||||
@@ -2736,17 +2798,17 @@ Authorization: Bearer YOUR_API_KEY</code></pre>
|
||||
|
||||
{
|
||||
slug: "best-qr-code-generator-2026",
|
||||
title: "Best QR Code Generator 2026: Top Tools + Checklist",
|
||||
description: "Best QR code generator 2026: compare dynamic tracking, design, reliability, API, and pricing. Use this checklist to pick the right tool for your needs.",
|
||||
excerpt: "We tested the top tools so you don't have to. See who leads the pack in 2026 for reliability, analytics depth, and design options.",
|
||||
title: "Best QR Code Generator 2026: Compared + Free Checklist",
|
||||
description: "We compared the top QR code generators in 2026 on dynamic QR, tracking, design, and price. Free checklist to pick the right tool for your exact use case.",
|
||||
excerpt: "We compared the top QR code generators in 2026 on dynamic QR, tracking, design, and price. See who wins and get a free checklist to pick the right one.",
|
||||
category: "Reviews",
|
||||
pillar: "basics",
|
||||
published: true,
|
||||
publishDate: "2026-03-09",
|
||||
date: "March 9, 2026",
|
||||
datePublished: "2026-03-09T09:00:00Z",
|
||||
dateModified: "2026-01-26T00:00:00Z",
|
||||
updatedAt: "2026-01-26",
|
||||
dateModified: "2026-05-04T00:00:00Z",
|
||||
updatedAt: "2026-05-04",
|
||||
authorSlug: "timo",
|
||||
readTime: "15 Min",
|
||||
image: "/blog/best-qr-generator-2026.png",
|
||||
@@ -2781,15 +2843,19 @@ Authorization: Bearer YOUR_API_KEY</code></pre>
|
||||
<div class="post-metadata bg-blue-50 p-4 rounded-lg mb-8 border-l-4 border-blue-500">
|
||||
<p class="text-sm text-gray-700">
|
||||
<strong>Author:</strong> Timo Knuth, QR Code & Marketing Expert<br/>
|
||||
📅 <strong>Published:</strong> March 9, 2026 | <strong>Last updated:</strong> January 26, 2026
|
||||
📅 <strong>Published:</strong> March 9, 2026 | <strong>Last updated:</strong> May 4, 2026
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2>Best QR Code Generator 2026: How to Choose the Right Tool</h2>
|
||||
<p>The best QR code generator 2026 depends on one thing: what you need the QR code to do after it's printed. For casual use, almost any generator works. For marketing and business, the best tools share a set of capabilities: dynamic QR codes, tracking, reliable redirects, branding, and management features.</p>
|
||||
<div class="bg-green-50 border border-green-200 rounded-xl p-5 mb-8">
|
||||
<p class="font-semibold text-green-900 mt-0 mb-1">Bottom line up front</p>
|
||||
<p class="text-green-800 mb-0"><strong>QR Master</strong> is the best free option for businesses in 2026 — free dynamic QR codes, real scan analytics, SVG export, and no scan limits. No credit card required. <a href="/create" class="text-green-700 underline font-semibold">Try it free →</a></p>
|
||||
</div>
|
||||
|
||||
<p>This guide gives you a "choose the right tool" checklist and a practical breakdown of common options — without forcing you into one single pick.</p>
|
||||
<p>Zapier's QR guide, for example, points out that different generators shine in different areas (business features, design customization, tracking).</p>
|
||||
<h2>Best QR Code Generator 2026: How to Choose the Right Tool</h2>
|
||||
<p>The best QR code generator in 2026 depends on one thing: what you need the QR code to do after it's printed. For casual use, almost any generator works. For marketing and business, the best tools share a core set of capabilities: dynamic QR codes, tracking, reliable redirects, branding, and management features.</p>
|
||||
|
||||
<p>This guide gives you a side-by-side comparison of the top tools and a practical checklist — so you can pick the right one for your exact use case without having to sign up for five free trials first.</p>
|
||||
|
||||
<p>According to <a href="https://www.statista.com/topics/1476/qr-codes/">Statista</a>, approx. <strong>45% of shoppers</strong> scanned a QR code in the past month, while QR code generation jumped <strong>238%</strong> from 2021-2023 (Uniqode). With this explosive growth, choosing the right generator is more important than ever.</p>
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ export const allIndustries: IndustryPage[] = [
|
||||
],
|
||||
tools: ["url-qr-code", "wifi-qr-code", "sms-qr-code"],
|
||||
faq: [
|
||||
{ question: "Are QR codes cost-effective for small cafes?", answer: "Yes! They eliminate menu reprinting costs, reduce paper waste, and many generators offer free basic plans." },
|
||||
{ question: "Are QR codes cost-effective for small cafes?", answer: "Yes! They eliminate menu reprinting costs, reduce paper waste, and many generators offer free basic plans. For a step-by-step menu setup, see the <a href=\"/blog/qr-code-restaurant-menu\" class=\"text-blue-600 underline\">Restaurant Menu QR Code Guide →</a>" },
|
||||
{ question: "Can I use one QR code for multiple purposes?", answer: "Yes, with dynamic QR codes you can easily update the destination URL to serve different purposes over time." },
|
||||
{ question: "How do cafes engage customers with QR?", answer: "Cafes link QR codes to loyalty sign-ups, Instagram profiles, and feedback forms to build lasting relationships." }
|
||||
],
|
||||
@@ -372,7 +372,7 @@ export const allIndustries: IndustryPage[] = [
|
||||
],
|
||||
tools: ["url-qr-code", "wifi-qr-code", "instagram-qr-code"],
|
||||
faq: [
|
||||
{ question: "How do bars use QR codes for menus?", answer: "Dynamic QR codes on table tents or bar top stickers link to a digital menu page. When you update the page, the code stays the same." },
|
||||
{ question: "How do bars use QR codes for menus?", answer: "Dynamic QR codes on table tents or bar top stickers link to a digital menu page. When you update the page, the code stays the same. See the full setup guide: <a href=\"/blog/qr-code-restaurant-menu\" class=\"text-blue-600 underline\">Restaurant Menu QR Code Guide →</a>" },
|
||||
{ question: "Can I show different menus for happy hour vs. regular hours?", answer: "Yes, with a dynamic QR code you can schedule URL redirects so the same physical code shows a happy hour menu during those specific hours." },
|
||||
{ question: "Where should bars place QR codes?", answer: "Table tents, bar top laminates, and bathroom mirrors are highest-traffic placements. Bathroom mirrors work especially well for event announcements." }
|
||||
],
|
||||
@@ -724,7 +724,7 @@ export const allIndustries: IndustryPage[] = [
|
||||
tools: ["url-qr-code", "instagram-qr-code", "vcard-qr-code"],
|
||||
faq: [
|
||||
{ question: "How do beauty salons use QR codes to get more bookings?", answer: "A QR code on the station mirror or checkout counter links directly to the booking platform. Clients rebook while still at the salon, capturing high-intent conversions." },
|
||||
{ question: "Can a QR code replace a printed price list at a salon?", answer: "Yes, link a QR to your service menu page. When prices change, update the page - the physical QR code never needs to be reprinted." },
|
||||
{ question: "Can a QR code replace a printed price list at a salon?", answer: "Yes, link a QR to your service menu page. When prices change, update the page — the physical QR code never needs to be reprinted. The same principle applies across hospitality: <a href=\"/blog/qr-code-restaurant-menu\" class=\"text-blue-600 underline\">see how restaurants handle this →</a>" },
|
||||
{ question: "What social platform should beauty salon QR codes link to?", answer: "Instagram is the strongest platform for beauty salons because transformation photos and styling reels perform extremely well there." }
|
||||
],
|
||||
placementTips: [
|
||||
|
||||
Reference in New Issue
Block a user