barcode
This commit is contained in:
parent
99acb37c83
commit
373e19a515
|
|
@ -38,6 +38,7 @@
|
|||
"qrcode": "^1.5.3",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-barcode": "^1.6.1",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
|
|
@ -6555,6 +6556,12 @@
|
|||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsbarcode": {
|
||||
"version": "3.12.3",
|
||||
"resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.12.3.tgz",
|
||||
"integrity": "sha512-CuHU9hC6dPsHF5oVFMo8NW76uQVjH4L22CsP4hW+dNnGywJHC/B0ThA1CTDVLnxKLrrpYdicBLnd2xsgTfRnvg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||
|
|
@ -8075,6 +8082,19 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-barcode": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-barcode/-/react-barcode-1.6.1.tgz",
|
||||
"integrity": "sha512-pc4ftnO5syHa/UjCruEeRsomlhoxKSugIgTA8T4dH0fvc89UMHL+/1Sp25IAphqG44pJkE5hMXhv89iS09jQyw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"jsbarcode": "^3.8.0",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "16 - 19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-chartjs-2": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz",
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
"qrcode": "^1.5.3",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-barcode": "^1.6.1",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
|
|
@ -90,4 +91,4 @@
|
|||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { usePathname } from 'next/navigation';
|
|||
import { Button } from '@/components/ui/Button';
|
||||
import { Footer } from '@/components/ui/Footer';
|
||||
import en from '@/i18n/en.json';
|
||||
import { ChevronDown, Wifi, Contact, MessageCircle, QrCode, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users } from 'lucide-react';
|
||||
import { ChevronDown, Wifi, Contact, MessageCircle, QrCode, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
||||
|
|
@ -62,6 +62,7 @@ export default function MarketingLayout({
|
|||
{ name: 'PayPal', description: 'Receive payments', href: '/tools/paypal-qr-code', icon: CreditCard, color: 'text-blue-700', bgColor: 'bg-blue-50' },
|
||||
{ name: 'Zoom', description: 'Join Zoom meeting', href: '/tools/zoom-qr-code', icon: Video, color: 'text-sky-500', bgColor: 'bg-sky-50' },
|
||||
{ name: 'Teams', description: 'Join Teams meeting', href: '/tools/teams-qr-code', icon: Users, color: 'text-violet-500', bgColor: 'bg-violet-50' },
|
||||
{ name: 'Barcode', description: 'Generate barcodes', href: '/tools/barcode-generator', icon: BarcodeIcon, color: 'text-slate-800', bgColor: 'bg-slate-100' },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -96,6 +97,7 @@ export default function MarketingLayout({
|
|||
<li><a href="/tools/paypal-qr-code">PayPal QR Code</a></li>
|
||||
<li><a href="/tools/zoom-qr-code">Zoom QR Code</a></li>
|
||||
<li><a href="/tools/teams-qr-code">Teams QR Code</a></li>
|
||||
<li><a href="/tools/barcode-generator">Barcode Generator</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,351 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
import Barcode from 'react-barcode';
|
||||
import Link from 'next/link';
|
||||
import { Download, Printer, Barcode as BarcodeIcon, Sparkles, Sliders, Check, Info } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { Select } from '@/components/ui/Select';
|
||||
import { showToast } from '@/components/ui/Toast';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { toPng, toSvg } from 'html-to-image';
|
||||
|
||||
// Brand Colors
|
||||
const BRAND = {
|
||||
paleGrey: '#EBEBDF',
|
||||
slate900: '#0f172a',
|
||||
};
|
||||
|
||||
const BARCODE_COLORS = [
|
||||
{ name: 'Classic Black', value: '#000000' },
|
||||
{ name: 'Dark Blue', value: '#1A1265' },
|
||||
{ name: 'Rich Indigo', value: '#4338CA' },
|
||||
{ name: 'Deep Emerald', value: '#065F46' },
|
||||
{ name: 'Crimson', value: '#991B1B' },
|
||||
{ name: 'Slate Gray', value: '#334155' },
|
||||
{ name: 'Business Navy', value: '#1E293B' },
|
||||
];
|
||||
|
||||
const FRAME_OPTIONS = [
|
||||
{ id: 'none', label: 'No Frame' },
|
||||
{ id: 'scanme', label: 'Scan Me' },
|
||||
{ id: 'product', label: 'Product' },
|
||||
{ id: 'serial', label: 'Serial' },
|
||||
];
|
||||
|
||||
const FORMAT_INFO: Record<string, string> = {
|
||||
'CODE128': 'High-density alphanumeric format. Best for general purpose use.',
|
||||
'EAN13': 'International retail standard for products worldwide.',
|
||||
'UPC': 'Standard retail format used primarily in North America.',
|
||||
'CODE39': 'Older industrial standard supporting uppercase letters and numbers.',
|
||||
'ITF14': 'Used on shipping containers and logistics packaging.',
|
||||
'MSI': 'Specialized format for retail shelf labeling and inventory.',
|
||||
'pharmacode': 'Pharmaceutical packaging control standard.',
|
||||
};
|
||||
|
||||
export default function BarcodeGeneratorClient() {
|
||||
const [value, setValue] = useState('123456789');
|
||||
const [format, setFormat] = useState('CODE128');
|
||||
const [width, setWidth] = useState(2);
|
||||
const [height, setHeight] = useState(100);
|
||||
const [displayValue, setDisplayValue] = useState(true);
|
||||
const [lineColor, setLineColor] = useState('#000000');
|
||||
const [frameType, setFrameType] = useState('none');
|
||||
|
||||
const barcodeRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const downloadBarcode = async (extension: 'png' | 'svg') => {
|
||||
if (!barcodeRef.current) return;
|
||||
|
||||
try {
|
||||
let dataUrl;
|
||||
if (extension === 'png') {
|
||||
dataUrl = await toPng(barcodeRef.current, {
|
||||
backgroundColor: '#ffffff',
|
||||
pixelRatio: 3,
|
||||
});
|
||||
} else {
|
||||
dataUrl = await toSvg(barcodeRef.current, {
|
||||
backgroundColor: '#ffffff',
|
||||
});
|
||||
}
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = dataUrl;
|
||||
link.download = `barcode-${value || 'generator'}.${extension}`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
showToast(`Barcode downloaded as ${extension.toUpperCase()}`, 'success');
|
||||
} catch (err) {
|
||||
console.error('Download failed', err);
|
||||
showToast('Download failed', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
const formats = [
|
||||
{ value: 'CODE128', label: 'Code 128 (Standard)' },
|
||||
{ value: 'EAN13', label: 'EAN-13 (Retail)' },
|
||||
{ value: 'UPC', label: 'UPC-A (US Retail)' },
|
||||
{ value: 'CODE39', label: 'Code 39' },
|
||||
{ value: 'ITF14', label: 'ITF-14' },
|
||||
{ value: 'MSI', label: 'MSI' },
|
||||
{ value: 'pharmacode', label: 'Pharmacode' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-5xl mx-auto px-4 md:px-6">
|
||||
|
||||
{/* Main Generator Card */}
|
||||
<div className="bg-white rounded-3xl shadow-2xl shadow-slate-900/10 overflow-hidden border border-slate-100">
|
||||
<div className="grid lg:grid-cols-2">
|
||||
|
||||
{/* LEFT: Input Section */}
|
||||
<div className="p-6 md:p-8 lg:p-10 space-y-8 border-r border-slate-100">
|
||||
|
||||
{/* Configuration */}
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<Sliders className="w-5 h-5 text-slate-900" />
|
||||
Configuration
|
||||
</h2>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">Content</label>
|
||||
<Input
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
placeholder="Enter barcode data (e.g. 12345678)"
|
||||
className="h-12 text-base rounded-xl border-slate-200 focus:border-slate-900 focus:ring-slate-900"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<label className="block text-sm font-medium text-slate-700">Format</label>
|
||||
<div className="group relative">
|
||||
<Info className="w-4 h-4 text-slate-400 cursor-help" />
|
||||
<div className="absolute right-0 bottom-full mb-2 w-64 p-3 bg-slate-900 text-white text-[11px] rounded-xl opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none shadow-xl z-50">
|
||||
<p className="font-bold mb-1">Format Guide:</p>
|
||||
<p>{FORMAT_INFO[format]}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Select
|
||||
value={format}
|
||||
onChange={(e) => setFormat(e.target.value)}
|
||||
className="h-12 rounded-xl border-slate-200"
|
||||
options={formats}
|
||||
aria-label="Format"
|
||||
/>
|
||||
<p className="text-[10px] text-slate-500 mt-2 px-1">
|
||||
{FORMAT_INFO[format]}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-slate-100"></div>
|
||||
|
||||
{/* Design Options */}
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<Sparkles className="w-5 h-5 text-slate-900" />
|
||||
Design Options
|
||||
</h2>
|
||||
|
||||
<div className="grid grid-cols-2 gap-6">
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between">
|
||||
<label className="text-sm font-medium text-slate-700">Width</label>
|
||||
<span className="text-xs text-slate-500 bg-slate-100 px-2 py-1 rounded-md font-bold">{width}px</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="4"
|
||||
step="0.5"
|
||||
value={width}
|
||||
onChange={(e) => setWidth(parseFloat(e.target.value))}
|
||||
className="w-full h-2 bg-slate-200 rounded-lg appearance-none cursor-pointer accent-slate-900"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between">
|
||||
<label className="text-sm font-medium text-slate-700">Height</label>
|
||||
<span className="text-xs text-slate-500 bg-slate-100 px-2 py-1 rounded-md font-bold">{height}px</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min="30"
|
||||
max="200"
|
||||
step="5"
|
||||
value={height}
|
||||
onChange={(e) => setHeight(parseInt(e.target.value))}
|
||||
className="w-full h-2 bg-slate-200 rounded-lg appearance-none cursor-pointer accent-slate-900"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-3">Line Color</label>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{BARCODE_COLORS.map((c) => (
|
||||
<button
|
||||
key={c.name}
|
||||
onClick={() => setLineColor(c.value)}
|
||||
className={cn(
|
||||
"w-9 h-9 rounded-full border-2 flex items-center justify-center transition-all hover:scale-110",
|
||||
lineColor === c.value ? "border-slate-900 ring-2 ring-offset-2 ring-slate-200" : "border-white shadow-md"
|
||||
)}
|
||||
style={{ backgroundColor: c.value }}
|
||||
aria-label={`Select ${c.name}`}
|
||||
title={c.name}
|
||||
>
|
||||
{lineColor === c.value && <Check className="w-4 h-4 text-white" strokeWidth={3} />}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-3">Frame Label</label>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-2">
|
||||
{FRAME_OPTIONS.map((frame) => (
|
||||
<button
|
||||
key={frame.id}
|
||||
onClick={() => setFrameType(frame.id)}
|
||||
className={cn(
|
||||
"py-2.5 px-3 rounded-lg text-sm font-medium transition-all border",
|
||||
frameType === frame.id
|
||||
? "bg-slate-900 text-white border-slate-900"
|
||||
: "bg-slate-50 text-slate-600 border-slate-200 hover:border-slate-300"
|
||||
)}
|
||||
>
|
||||
{frame.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label className="flex items-center gap-3 cursor-pointer group p-3 border border-slate-200 rounded-xl hover:border-slate-900 transition-colors bg-slate-50/50">
|
||||
<div className={cn(
|
||||
"w-5 h-5 rounded border-2 flex items-center justify-center transition-all",
|
||||
displayValue ? "bg-slate-900 border-slate-900" : "border-slate-300 group-hover:border-slate-400"
|
||||
)}>
|
||||
{displayValue && <Check className="w-3.5 h-3.5 text-white" strokeWidth={3} />}
|
||||
</div>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={displayValue}
|
||||
onChange={(e) => setDisplayValue(e.target.checked)}
|
||||
className="sr-only"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-700">Show Value Text</span>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT: Preview Section */}
|
||||
<div className="p-6 md:p-8 lg:p-10 flex flex-col items-center justify-center" style={{ backgroundColor: BRAND.paleGrey }}>
|
||||
|
||||
{/* Barcode Card */}
|
||||
<div
|
||||
className="bg-white rounded-3xl shadow-xl p-8 flex flex-col items-center justify-center min-h-[300px] w-full max-w-[400px] border border-slate-100 relative"
|
||||
>
|
||||
<div className="absolute top-4 right-4">
|
||||
<div className="flex items-center gap-1.5 px-2 py-1 bg-slate-100 rounded-md text-[10px] font-bold text-slate-500 uppercase tracking-wider">
|
||||
Live Preview
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ref={barcodeRef} className="py-4 bg-white flex flex-col items-center justify-center overflow-hidden w-full">
|
||||
{frameType !== 'none' && (
|
||||
<div
|
||||
className="mb-4 px-6 py-2 rounded-full text-white font-bold text-xs tracking-widest uppercase shadow-md"
|
||||
style={{ backgroundColor: lineColor }}
|
||||
>
|
||||
{FRAME_OPTIONS.find(f => f.id === frameType)?.label}
|
||||
</div>
|
||||
)}
|
||||
{value ? (
|
||||
<Barcode
|
||||
key={`${format}-${lineColor}-${value}-${width}-${height}-${displayValue}`}
|
||||
value={value}
|
||||
format={format as any}
|
||||
width={width}
|
||||
height={height}
|
||||
displayValue={displayValue}
|
||||
background="#ffffff"
|
||||
lineColor={lineColor}
|
||||
margin={10}
|
||||
/>
|
||||
) : (
|
||||
<div className="text-center text-slate-400 p-6">
|
||||
<BarcodeIcon className="w-12 h-12 mx-auto mb-3 opacity-30" />
|
||||
<p className="text-sm font-medium">Enter data to generate</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Info Preview */}
|
||||
<div className="mt-6 text-center w-full">
|
||||
<h3 className="font-bold text-slate-900 text-lg flex items-center justify-center gap-2 truncate">
|
||||
<span className="truncate">{formats.find(f => f.value === format)?.label}</span>
|
||||
</h3>
|
||||
<div className="text-xs text-slate-600 mt-1 truncate px-2 font-mono">
|
||||
{value || 'Barcode Value'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Download Buttons */}
|
||||
<div className="flex flex-col sm:flex-row items-center gap-3 mt-8 w-full max-w-[450px]">
|
||||
<Button
|
||||
onClick={() => downloadBarcode('png')}
|
||||
className="w-full sm:flex-1 bg-slate-900 hover:bg-black text-white shadow-lg h-12 rounded-xl"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Download PNG
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => downloadBarcode('svg')}
|
||||
variant="outline"
|
||||
className="w-full sm:w-auto px-6 border-slate-300 hover:bg-white h-12 rounded-xl font-bold"
|
||||
>
|
||||
SVG
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => window.print()}
|
||||
variant="outline"
|
||||
className="w-full sm:w-auto px-4 border-slate-300 hover:bg-white h-12 rounded-xl"
|
||||
>
|
||||
<Printer className="w-4 h-4 text-slate-600" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Upsell Banner */}
|
||||
<div className="mt-8 bg-gradient-to-r from-slate-900 to-slate-700 rounded-2xl p-6 flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||
<div className="text-white text-center sm:text-left">
|
||||
<h3 className="font-bold text-lg">Need Dynamic QR Codes?</h3>
|
||||
<p className="text-white/80 text-sm mt-1">
|
||||
Switch to QR codes to edit content later and track your scans.
|
||||
</p>
|
||||
</div>
|
||||
<Link href="/signup">
|
||||
<Button className="bg-white text-slate-900 hover:bg-slate-100 shrink-0 shadow-lg px-8">
|
||||
Get Started Free
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import BarcodeGeneratorClient from './BarcodeGeneratorClient';
|
||||
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';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free Online Barcode Generator | Create EAN, UPC, Code 128 | QR Master',
|
||||
},
|
||||
description: 'Create professional, printable barcodes instantly. Erstelle EAN, UPC & Code 128 Barcodes kostenlos. Download as PNG or SVG. No sign-up required.',
|
||||
keywords: ['barcode generator', 'online barcode maker', 'create barcode free', 'ean-13 generator', 'upc-a generator', 'code 128 generator', 'barcode creator', 'printable barcodes'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free Online Barcode Generator | QR Master',
|
||||
description: 'Generate custom printable barcodes instantly. Supports EAN, UPC, Code 128.',
|
||||
url: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
siteName: 'QR Master',
|
||||
locale: 'en_US',
|
||||
type: 'website',
|
||||
images: [{ url: '/og-barcode-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free Online Barcode Generator',
|
||||
description: 'Create custom barcodes in seconds. Download high-quality PNG/SVG.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'Barcode Generator',
|
||||
'Generate custom printable barcodes instantly for EAN, UPC, Code 128 and more.',
|
||||
'/og-barcode-generator.png',
|
||||
'UtilitiesApplication'
|
||||
),
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a Barcode',
|
||||
description: 'Create custom barcodes for products or inventory.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Content',
|
||||
text: 'Type or paste the numeric or alphanumeric data for your barcode.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Select Format',
|
||||
text: 'Choose the appropriate barcode type (e.g., Code 128 for general use, EAN-13 for retail).',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Customize Design',
|
||||
text: 'Adjust the height and width of the barcode to fit your needs.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Toggle Text',
|
||||
text: 'Decide if you want the human-readable value to appear below the barcode.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Download & Print',
|
||||
text: 'Save your barcode as PNG or SVG and print it for labels or inventory.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT20S',
|
||||
},
|
||||
generateFaqSchema({
|
||||
'What is the best barcode format for general use?': {
|
||||
question: 'What is the best barcode format for general use?',
|
||||
answer: 'Code 128 is the most versatile format and is highly recommended for inventory and internal tracking as it supports both numbers and letters.',
|
||||
},
|
||||
'Which format should I use for retail?': {
|
||||
question: 'Which format should I use for retail?',
|
||||
answer: 'EAN-13 is the standard for retail products in Europe and worldwide, while UPC-A is the standard for retail in North America.',
|
||||
},
|
||||
'Is this barcode generator free?': {
|
||||
question: 'Is this barcode generator free?',
|
||||
answer: 'Yes, our online barcode generator is completely free to use with no hidden costs or sign-ups required.',
|
||||
},
|
||||
'Can I download barcodes in vector format?': {
|
||||
question: 'Can I download barcodes in vector format?',
|
||||
answer: 'Yes, you can download your barcodes as SVG (Scalable Vector Graphics), which is ideal for high-quality printing without loss of resolution.',
|
||||
},
|
||||
'Do these barcodes work with any scanner?': {
|
||||
question: 'Do these barcodes work with any scanner?',
|
||||
answer: 'Yes, we generate standard-compliant barcodes that are universally readable by any standard optical or laser barcode scanner.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function BarcodeGeneratorPage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<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">
|
||||
<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>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#barcode_pattern)" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-400"></span>
|
||||
</span>
|
||||
Free Tool — Professional & Fast
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
Professional <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-indigo-400">Online Barcode Generator</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-slate-400 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Create and print high-quality barcodes for your products and inventory.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Supports EAN, UPC, Code 128.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Retail Ready
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Vector SVG Export
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
No Registration
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-blue-500/10 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform rotate-2 hover:-rotate-1 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/5 to-transparent rounded-3xl" />
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<div className="text-[10px] font-mono font-bold tracking-widest uppercase">98234001A</div>
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -right-6 bg-slate-900 border border-white/10 py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-blue-500/20 p-2 rounded-full">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<BarcodeGeneratorClient />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How Our Barcode Generator Works
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-black flex items-center justify-center mx-auto mb-4">
|
||||
<Sliders className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Configure</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Enter your data and select the format.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-black flex items-center justify-center mx-auto mb-4">
|
||||
<Sparkles className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Customize</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Adjust height, width and text display.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-black flex items-center justify-center mx-auto mb-4">
|
||||
<Zap className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Preview</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
See your barcode update in real-time.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-black flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Save as professional PNG or SVG.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-black flex items-center justify-center mx-auto mb-4">
|
||||
<Printer className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Print</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Print labels directly from your browser.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* RELATED TOOLS */}
|
||||
<RelatedTools />
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about our online barcode creator.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="What is the best barcode format for general use?"
|
||||
answer="Code 128 is the most versatile format and is highly recommended for inventory and internal tracking as it supports both numbers and letters."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Which format should I use for retail?"
|
||||
answer="EAN-13 is the standard for retail products in Europe and worldwide, while UPC-A is the standard for retail in North America."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is this barcode generator free?"
|
||||
answer="Yes, our online barcode generator is completely free to use with no hidden costs or sign-ups required."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I download barcodes in vector format?"
|
||||
answer="Yes, you can download your barcodes as SVG (Scalable Vector Graphics), which is ideal for high-quality printing without loss of resolution."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Do these barcodes work with any scanner?"
|
||||
answer="Yes, we generate standard-compliant barcodes that are universally readable by any standard optical or laser barcode scanner."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
import React, { useState, useRef } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { toPng } from 'html-to-image';
|
||||
|
||||
import {
|
||||
Link as LinkIcon,
|
||||
|
|
@ -52,7 +53,6 @@ export default function URLGenerator() {
|
|||
if (!qrRef.current) return;
|
||||
try {
|
||||
if (format === 'png') {
|
||||
const { toPng } = await import('html-to-image');
|
||||
const dataUrl = await toPng(qrRef.current, { cacheBust: true, pixelRatio: 3 });
|
||||
const link = document.createElement('a');
|
||||
link.download = `url-qr-code.png`;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { usePathname } from 'next/navigation';
|
|||
import { Button } from '@/components/ui/Button';
|
||||
import { Footer } from '@/components/ui/Footer';
|
||||
import de from '@/i18n/de.json';
|
||||
import { ChevronDown, Wifi, Contact, MessageCircle, QrCode, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users } from 'lucide-react';
|
||||
import { ChevronDown, Wifi, Contact, MessageCircle, QrCode, Link2, Type, Mail, MessageSquare, Phone, Calendar, MapPin, Facebook, Instagram, Twitter, Youtube, Music, Bitcoin, CreditCard, Video, Users, Barcode as BarcodeIcon } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
||||
|
|
@ -62,6 +62,7 @@ export default function MarketingLayout({
|
|||
{ name: 'PayPal', description: 'Receive payments', href: '/tools/paypal-qr-code', icon: CreditCard, color: 'text-blue-700', bgColor: 'bg-blue-50' },
|
||||
{ name: 'Zoom', description: 'Join Zoom meeting', href: '/tools/zoom-qr-code', icon: Video, color: 'text-sky-500', bgColor: 'bg-sky-50' },
|
||||
{ name: 'Teams', description: 'Join Teams meeting', href: '/tools/teams-qr-code', icon: Users, color: 'text-violet-500', bgColor: 'bg-violet-50' },
|
||||
{ name: 'Barcode', description: 'Barcode erstellen', href: '/tools/barcode-generator', icon: BarcodeIcon, color: 'text-slate-800', bgColor: 'bg-slate-100' },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -96,6 +97,7 @@ export default function MarketingLayout({
|
|||
<li><a href="/tools/paypal-qr-code">PayPal QR Code</a></li>
|
||||
<li><a href="/tools/zoom-qr-code">Zoom QR Code</a></li>
|
||||
<li><a href="/tools/teams-qr-code">Teams QR Code</a></li>
|
||||
<li><a href="/tools/barcode-generator">Barcode Generator</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { Features } from '@/components/marketing/Features';
|
|||
import { Pricing } from '@/components/marketing/Pricing';
|
||||
import { FAQ } from '@/components/marketing/FAQ';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import de from '@/i18n/de.json';
|
||||
|
||||
function truncateAtWord(text: string, maxLength: number): string {
|
||||
|
|
@ -102,6 +103,9 @@ export default function QRCodeErstellenPage() {
|
|||
{/* Main Interaction: Generator */}
|
||||
<InstantGenerator t={t} />
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
<StaticVsDynamic t={t} />
|
||||
<Features t={t} />
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
|||
'paypal-qr-code',
|
||||
'zoom-qr-code',
|
||||
'teams-qr-code',
|
||||
'barcode-generator',
|
||||
];
|
||||
|
||||
// All blog posts
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import {
|
|||
MapPin,
|
||||
CreditCard,
|
||||
Video,
|
||||
Users
|
||||
Users,
|
||||
Barcode
|
||||
} from 'lucide-react';
|
||||
|
||||
const TOOLS = [
|
||||
|
|
@ -177,6 +178,14 @@ const TOOLS = [
|
|||
href: '/tools/teams-qr-code',
|
||||
color: 'text-violet-500',
|
||||
bg: 'bg-violet-50'
|
||||
},
|
||||
{
|
||||
icon: Barcode,
|
||||
name: 'Barcode',
|
||||
description: 'Create standard barcodes',
|
||||
href: '/tools/barcode-generator',
|
||||
color: 'text-slate-900',
|
||||
bg: 'bg-slate-100'
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ import {
|
|||
Bitcoin,
|
||||
CreditCard,
|
||||
Video,
|
||||
Users
|
||||
Users,
|
||||
Barcode
|
||||
} from 'lucide-react';
|
||||
|
||||
const tools = [
|
||||
|
|
@ -29,7 +30,7 @@ const tools = [
|
|||
{ name: 'Email', href: '/tools/email-qr-code', icon: Mail, color: 'text-amber-500', bgColor: 'bg-amber-50' },
|
||||
{ name: 'SMS', href: '/tools/sms-qr-code', icon: MessageSquare, color: 'text-cyan-500', bgColor: 'bg-cyan-50' },
|
||||
{ name: 'Instagram', href: '/tools/instagram-qr-code', icon: Instagram, color: 'text-pink-600', bgColor: 'bg-pink-50' },
|
||||
{ name: 'TikTok', href: '/tools/tiktok-qr-code', icon: Music, color: 'text-slate-800', bgColor: 'bg-slate-100' },
|
||||
{ name: 'Barcode', href: '/tools/barcode-generator', icon: Barcode, color: 'text-slate-900', bgColor: 'bg-slate-100' },
|
||||
];
|
||||
|
||||
export function RelatedTools() {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export function middleware(req: NextRequest) {
|
|||
'/bulk-qr-code-generator',
|
||||
'/qr-code-tracking',
|
||||
'/reprint-calculator',
|
||||
'/barcode-generator',
|
||||
];
|
||||
|
||||
// Check if path is public
|
||||
|
|
|
|||
Loading…
Reference in New Issue