Skip to main content

Technical Architecture

The QR Generator is built as a modern, client-side Progressive Web App using Vue 3 and Vite.


Technology Stack

Frontend Framework

  • Vue 3.5+ with Composition API
  • TypeScript for type safety
  • Vite 5 for fast builds and HMR
  • Vue Router for SPA navigation

UI & Styling

  • Tailwind CSS 3 for utility-first styling
  • Radix Vue for accessible components
  • VueUse for composable utilities
  • Dark mode support with system preference detection

QR Code Library

Custom fork of qr-code-styling with enhancements:

  • Core: qrcode-generator library
  • Rendering: Custom SVG renderer
  • Styling: 6 dot styles, 4 corner styles
  • Image overlay: Logo/image embedding
  • Export: PNG, JPG, SVG, ASCII formats

Encryption

  • Web Crypto API (native browser implementation)
  • Algorithm: AES-GCM 256-bit
  • Key Derivation: PBKDF2 with 100,000 iterations
  • Zero dependencies: No external crypto libraries

PWA Features

  • Vite PWA Plugin with Workbox
  • Service Worker: Pre-caching and runtime caching
  • Offline support: Full functionality offline after first visit
  • Install prompts: Desktop and mobile app installation

Internationalization

  • Vue I18n: Translation management
  • 45+ languages: Including CJK, RTL, and emoji support
  • Dynamic loading: Lazy-load language files
  • Locale detection: Auto-detect user's preferred language

Architecture Patterns

Component Structure

App.vue (Root)
├── LanguageSelector.vue
├── MobileMenu.vue
└── Router
├── QRCodeCreate.vue (Main creation UI)
│ ├── StyledQRCode.vue (QR renderer)
│ ├── QRCodeFrame.vue (Frame overlay)
│ ├── DataTemplatesModal.vue (Templates)
│ ├── CopyImageModal.vue (Copy UI)
│ ├── TextExportModal.vue (ASCII export)
│ ├── BatchExportFieldsGuide.vue (CSV help)
│ └── ui/* (Reusable components)

└── QRCodeScan.vue (Scanning UI)
└── QRCodeCameraScanner.vue (Camera interface)

State Management

No Vuex/Pinia — Uses composition API with:

  • ref() and reactive() for local state
  • computed() for derived state
  • watch() for side effects
  • localStorage for persistence
  • Event emitters for component communication

Data Flow

User Input → Vue Reactive State → QR Generation → Render to Canvas/SVG

Display + Export

Key Modules

QR Code Generation (src/lib/qr-code/)

lib/qr-code/
├── core.ts # Main QR code instance & config
├── matrix.ts # Binary matrix generation
├── render/
│ ├── svg.ts # SVG rendering engine
│ └── canvas.ts # Canvas rasterization (PNG/JPG)
├── frame.ts # Frame overlay logic
├── types.ts # TypeScript type definitions
└── legacy-adapter.ts # Backward compatibility

Key functions:

  • createQRCode(config) — Main entry point
  • buildMatrix(data, ecLevel) — Generate QR matrix
  • renderQrFragment() — Create SVG elements
  • rasterizeSvg() — Convert SVG to PNG/JPG

Encryption (src/utils/encryption.ts)

// Encrypt data with password
export async function encryptData(
data: string,
password: string
): Promise<string>

// Decrypt encrypted data
export async function decryptData(
encryptedData: string,
password: string
): Promise<string>

// Check if data is encrypted
export function isEncrypted(data: string): boolean

Presets (src/utils/qrCodePresets.ts)

Pre-configured style combinations:

  • Color schemes
  • Dot/corner styles
  • Background colors
  • Border radius
  • Default logos

Built-in presets:

  • Vercel Light/Dark
  • Supabase Green/Purple
  • VueJS
  • Padlet
  • UIlicious
  • Scottsdale (custom)
  • And more...

Data Encoding (src/utils/dataEncoding.ts)

Encode structured data types:

export const generateUrlData = (data: { url: string }): string
export const generateEmailData = (data: EmailData): string
export const generatePhoneData = (data: { phone: string }): string
export const generateSmsData = (data: SmsData): string
export const generateWifiData = (data: WifiData): string
export const generateVCardData = (data: VCardData): string
export const generateCalendarData = (data: CalendarData): string
export const generateLocationData = (data: LocationData): string

Batch Processing (src/utils/csvBatchProcessing.ts)

// Parse and validate CSV
export function processCsvDataForBatch(
csvData: CSVData[]
): BatchProcessingResult

// Generate unique filenames
export function generateBatchExportFilename(
dataString: string,
frameText: string,
customFileName: string,
index: number,
usedFilenames: Set<string>
): string

Build Process

Development

npm run dev
  • Vite dev server on http://localhost:5173
  • Hot Module Replacement (HMR)
  • TypeScript checking
  • CSS preprocessing

Production Build

npm run build

Build outputs:

dist/
├── index.html # Entry point
├── manifest.webmanifest # PWA manifest
├── sw.js # Service worker
├── workbox-*.js # Workbox runtime
├── assets/
│ ├── index-[hash].js # Main JS bundle (~1.8MB)
│ ├── index-[hash].css # Compiled CSS (~86KB)
│ └── *.png/svg # Static assets
├── app_icons/ # PWA icons
├── batch_export_templates/ # CSV templates
└── presets/ # Preset logos

Optimizations:

  • Code splitting (dynamic imports)
  • Tree shaking (unused code removal)
  • Minification (Terser)
  • CSS purging (PurgeCSS via Tailwind)
  • Asset optimization (images, fonts)
  • Gzip compression (via .htaccess)

Deployment

Static Hosting

The app is fully static — no backend required.

Requirements:

  • Web server (Apache, Nginx, Caddy, etc.)
  • HTTPS (for camera access and PWA)
  • URL rewriting for SPA routing

Hosted on:

  • cPanel/Apache
  • Domain: qr-generator.scottsdalemint.com
  • Static files in public_html/

.htaccess Configuration

# SPA routing - serve index.html for all routes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [L]

# Security headers
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"

# Caching
<FilesMatch "\.(js|css|png|jpg|gif|svg|woff2)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>

# Service worker - no cache
<Files "sw.js">
Header set Cache-Control "max-age=0, no-cache"
</Files>

Environment Variables

Build-time variables (via .env):

VITE_DEFAULT_DATA_TO_ENCODE=https://scottsdalemint.com
VITE_DEFAULT_PRESET=Default (lyqht)

Runtime: None required (all client-side)


Performance Characteristics

Bundle Size

AssetUncompressedGzipped
JavaScript~1.8MB~670KB
CSS~86KB~13KB
Total (first load)~1.9MB~683KB

Why large JS bundle?

  • QR code generation library
  • Image processing libraries
  • QR scanning libraries (html5-qrcode, nimiq/qr-scanner)
  • 45 language files
  • PWA runtime

Mitigations:

  • Lazy-load languages (only load active language)
  • Service worker caching (loads once, cached forever)
  • Offline-first (no subsequent network requests)

Load Performance

First Visit:

  • Initial load: ~2-3 seconds (depends on network)
  • Time to interactive: ~3-4 seconds
  • PWA install prompt: After 5 seconds

Subsequent Visits:

  • Instant load (service worker cache)
  • ~100-200ms to interactive
  • Full offline functionality

Runtime Performance

  • QR generation: ~50-100ms per code
  • Batch export (100 codes): ~30-60 seconds
  • Encryption: ~50-100ms per operation
  • Scanning: Real-time (30fps camera)

Browser Compatibility

Supported Browsers

BrowserMinimum VersionNotes
Chrome76+Full support
Edge79+Full support
Firefox90+Full support
Safari13.1+Limited clipboard API
Chrome Mobile76+Full support
Safari iOS13.1+PWA installable
Samsung Internet12+Full support

Required APIs

  • ES6+ — Modern JavaScript
  • Web Crypto API — Encryption
  • Service Workers — PWA/offline
  • IndexedDB — Local storage
  • Media Devices API — Camera access
  • Canvas API — Image generation
  • ⚠️ Clipboard API — Limited Safari support
  • ⚠️ Web Share API — Optional, mobile-mostly

Not supported:

  • ❌ Internet Explorer
  • ❌ Legacy Edge (before version 79)
  • ❌ Older mobile browsers

Security Considerations

Client-Side Only

Advantages:

  • ✅ No data leaves user's device
  • ✅ No server-side vulnerabilities
  • ✅ No database to compromise
  • ✅ Privacy by design

Implications:

  • All processing in browser memory
  • No user accounts or authentication
  • No server-side validation
  • No telemetry or analytics

Encryption Security

  • AES-GCM: Military-grade encryption
  • 256-bit keys: Quantum-resistant
  • PBKDF2: Brute-force resistant (100k iterations)
  • Random salts/IVs: Unique per encryption
  • No password storage: User must remember

Attack surface:

  • Password phishing (social engineering)
  • Weak passwords (user responsibility)
  • Browser compromise (malware)

Content Security Policy

Recommended CSP headers:

Content-Security-Policy:
default-src 'self';
script-src 'self' 'wasm-unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob:;
font-src 'self' data:;
connect-src 'self';
media-src 'self' blob:;

Testing

Manual Testing

Test matrix:

  • ✅ QR code creation (all data types)
  • ✅ QR code scanning (camera + upload)
  • ✅ Encryption/decryption flow
  • ✅ Batch export (CSV processing)
  • ✅ PWA installation
  • ✅ Offline functionality
  • ✅ Cross-browser compatibility
  • ✅ Mobile responsiveness
  • ✅ Accessibility (keyboard nav, screen readers)

Automated Testing

Not currently implemented:

  • Unit tests (Vitest)
  • E2E tests (Playwright)
  • Component tests (Vue Test Utils)

Reason: MVP prioritized features over test coverage.


Future Enhancements

Planned Features

  1. Advanced Batch Processing

    • Per-row encryption passwords
    • Variable error correction levels
    • Preview mode before export
  2. QR Code Templates

    • Save custom templates
    • Share templates via URL
    • Template marketplace
  3. Enhanced Encryption

    • Multiple encryption algorithms
    • Key sharing via QR code
    • Password strength meter
  4. Analytics (Privacy-Preserving)

    • Local-only usage stats
    • No tracking, no servers
    • Exportable JSON reports
  5. Advanced Customization

    • Gradient colors
    • Custom shapes (hearts, stars)
    • Animation support (animated GIFs)
    • 3D QR codes

Development Workflow

Local Development

# Clone repository
git clone [repo-url]
cd mini-qr

# Install dependencies
npm install

# Run dev server
npm run dev

# Build for production
npm run build

# Preview production build
npm run preview

Code Style

  • ESLint for linting
  • Prettier for formatting (auto-format on save)
  • TypeScript strict mode
  • Vue 3 best practices (Composition API)

Git Workflow

  • main branch for production
  • Feature branches for development
  • Pull requests for code review
  • Semantic commit messages

Next Steps