Skip to content

Full-stack web application for generating and managing qr-code generation with customizable options for different usecases

Notifications You must be signed in to change notification settings

dhiway/QR-code-gen

Repository files navigation

QR Code Generator

A high-performance QR code generation system built with Rust and SolidJS. Supports URL, text, vCard, WiFi, and email QR codes with customizable colors, logo embedding, and bulk generation.

Ships as a REST API, CLI tool, and web frontend — all from a single codebase, deployable as a single Docker container.


Table of Contents


Features

  • Multiple QR content types — URL, plain text, vCard contacts, WiFi credentials, email
  • Multiple output formats — PNG, SVG, JPEG
  • Custom styling — foreground/background colors, configurable size (128–2048px)
  • Logo embedding — overlay a logo image in the center of the QR code
  • Error correction levels — Low, Medium, Quartile, High
  • Quiet zone control — configurable margin (0–10 modules)
  • Bulk generation — submit a list of items, receive a ZIP archive
  • REST API with JSON request/response and binary image download
  • Interactive API docs — auto-generated Swagger UI via OpenAPI
  • CLI tool — generate QR codes from the command line
  • Web frontend — dark-themed, responsive SolidJS single-page app
  • API key authentication — configurable via environment variables
  • Per-IP rate limiting — in-memory, configurable requests/minute
  • Graceful shutdown — handles SIGTERM properly for container orchestration
  • Single Docker container — API + frontend + CLI in one image (~50–80MB)

Tech Stack

Layer Technology
Core QR Library Rust — qrcode, image, zip crates
REST API Rust — Axum, Tokio, Tower, tower-http
API Documentation utoipa + Swagger UI (auto-generated OpenAPI)
CLI Rust — Clap v4
Frontend SolidJS + TypeScript
Frontend Tooling Bun + Vite
Deployment Docker (multi-stage build)

Project Structure

qr-code-gen/
├── Cargo.toml                          # Workspace root
├── Cargo.lock                          # Locked dependencies (committed for reproducible builds)
├── Dockerfile                          # Multi-stage build (Bun + Rust → Debian slim)
├── docker-compose.yml                  # Single-command production deployment
├── .env.example                        # Environment variable reference
├── .gitignore
├── .dockerignore
│
├── postman/
│   └── QR_Code_Generator_API.postman_collection.json   # Importable Postman collection
│
├── crates/
│   ├── qr-core/                        # Core QR generation library
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs                  # Public API and re-exports
│   │       ├── generator.rs            # QR generation engine (PNG/SVG/JPEG + logo overlay)
│   │       ├── types.rs                # Content types (URL, vCard, WiFi, Email)
│   │       ├── style.rs                # Styling: colors, size, quiet zone, logo config
│   │       ├── bulk.rs                 # Bulk generation → ZIP archive
│   │       └── error.rs                # Error types
│   │
│   ├── qr-api/                         # Axum REST API server
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── main.rs                 # Server setup, routing, Swagger UI, static file serving
│   │       ├── config.rs               # Environment-based configuration
│   │       ├── state.rs                # Shared app state + in-memory rate limiter
│   │       ├── errors.rs               # Structured API error responses
│   │       ├── models.rs               # Request/response types with OpenAPI schemas
│   │       ├── routes/
│   │       │   ├── mod.rs
│   │       │   ├── generate.rs         # POST /api/generate, POST /api/generate/base64
│   │       │   ├── bulk.rs             # POST /api/bulk
│   │       │   └── health.rs           # GET /health
│   │       └── middleware/
│   │           ├── mod.rs
│   │           ├── auth.rs             # API key authentication
│   │           └── rate_limit.rs       # Per-IP rate limiting
│   │
│   └── qr-cli/                         # Command-line tool
│       ├── Cargo.toml
│       └── src/
│           └── main.rs                 # Clap-based CLI with url/text/vcard/wifi/email/bulk subcommands
│
├── frontend/                           # SolidJS single-page application
│   ├── package.json
│   ├── bun.lock
│   ├── tsconfig.json
│   ├── vite.config.ts                  # Vite config with API proxy for dev
│   ├── index.html
│   └── src/
│       ├── index.tsx                   # App entry point
│       ├── App.tsx                     # Main app layout (Single/Bulk tabs)
│       ├── api/
│       │   └── client.ts              # Typed API client functions
│       ├── components/
│       │   ├── TypeSelector.tsx        # URL / Text / vCard / WiFi / Email tabs
│       │   ├── QrForm.tsx              # Content input forms for each type
│       │   ├── StyleOptions.tsx        # Colors, size, error correction, logo upload
│       │   ├── QrPreview.tsx           # Live preview + download buttons (PNG/SVG/JPEG)
│       │   └── BulkUpload.tsx          # JSON/URL list input → ZIP download
│       └── styles/
│           └── global.css              # Dark theme, responsive layout
│
└── tests/
    └── integration/                    # Integration tests (future)

Getting Started

Prerequisites

For local development:

  • Rust (1.75+ recommended)
  • Bun (1.0+) — for frontend builds
  • (Optional) Docker — for containerized deployment

For Docker-only deployment:

  • Docker and Docker Compose — that's it, nothing else needed

Local Development

1. Clone the repository:

git clone <your-repo-url>
cd qr-code-gen

2. Build the frontend:

cd frontend
bun install
bun run build
cd ..

3. Run the API server:

cargo run -p qr-api

The server starts at http://localhost:3000 with:

  • Web frontend at /
  • API endpoints at /api/*
  • Swagger docs at /api/docs

No environment setup required for local development — all config has sensible defaults.

For frontend hot-reload during development (optional), run two terminals:

# Terminal 1: Rust API server
cargo run -p qr-api

# Terminal 2: Vite dev server with hot module replacement
cd frontend && bun run dev

Then open http://localhost:5173 — Vite proxies API requests to the Rust server automatically.

Note: cargo run compiles in debug mode (fast compilation, slower runtime). This is fine for development. The Docker build uses --release for optimized production binaries.

Docker Deployment

Single command — builds and runs everything:

docker compose up --build

This:

  1. Builds the SolidJS frontend with Bun
  2. Compiles optimized Rust binaries with cargo build --release
  3. Creates a slim runtime image (~50–80MB)
  4. Starts the server on port 3000

Open http://localhost:3000 — frontend, API, and Swagger docs all served from one container.

To run in the background:

docker compose up --build -d

To stop:

docker compose down

Usage

Web Frontend

Open http://localhost:3000 in your browser. The frontend provides:

  • Single mode — Generate one QR code at a time

    • Select content type (URL, Text, vCard, WiFi, Email)
    • Fill in the form fields
    • Customize colors, size, error correction level, and quiet zone
    • Upload a logo image for center overlay
    • Click "Generate QR Code" to preview
    • Download as PNG, SVG, or JPEG
  • Bulk mode — Generate multiple QR codes at once

    • Paste a list of URLs (one per line) or a JSON array of items
    • Upload a JSON file
    • Download all generated QR codes as a ZIP archive

REST API

Generate a QR code (binary image):

curl -X POST http://localhost:3000/api/generate \
  -H "Content-Type: application/json" \
  -d '{
    "content": {"type": "Url", "data": "https://example.com"},
    "format": "Png",
    "error_correction": "Medium",
    "style": {
      "size": 512,
      "foreground_color": "#000000",
      "background_color": "#FFFFFF",
      "quiet_zone": 2,
      "logo_size_percent": 20
    }
  }' \
  --output qrcode.png

Generate a QR code (base64 JSON):

curl -X POST http://localhost:3000/api/generate/base64 \
  -H "Content-Type: application/json" \
  -d '{
    "content": {"type": "Url", "data": "https://example.com"},
    "format": "Png",
    "error_correction": "Medium",
    "style": {"size": 512}
  }'

Response:

{
  "image": "iVBORw0KGgo...",
  "data_uri": "data:image/png;base64,iVBORw0KGgo...",
  "content_type": "image/png",
  "size_bytes": 2450
}

Generate WiFi QR code:

curl -X POST http://localhost:3000/api/generate \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "type": "WiFi",
      "data": {
        "ssid": "MyNetwork",
        "encryption": "WPA",
        "password": "secret123",
        "hidden": false
      }
    },
    "format": "Png",
    "error_correction": "High",
    "style": {"size": 512}
  }' \
  --output wifi-qr.png

Bulk generation (ZIP):

curl -X POST http://localhost:3000/api/bulk \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "name": "example-1",
        "content": {"type": "Url", "data": "https://example.com"},
        "format": "Png",
        "error_correction": "Medium",
        "style": {"size": 512}
      },
      {
        "name": "github",
        "content": {"type": "Url", "data": "https://github.com"},
        "format": "Svg",
        "error_correction": "High",
        "style": {"size": 256}
      }
    ]
  }' \
  --output qrcodes.zip

CLI Tool

# Generate URL QR code
cargo run -p qr-cli -- url "https://example.com" -o qrcode.png

# Generate with custom colors and size
cargo run -p qr-cli -- url "https://github.com" \
  --fg-color "#1e40af" --bg-color "#eff6ff" \
  -s 1024 -o blue-qr.png

# Generate SVG format
cargo run -p qr-cli -- url "https://example.com" -f svg -o qrcode.svg

# Generate vCard contact QR
cargo run -p qr-cli -- vcard \
  --first-name "John" --last-name "Doe" \
  --phone "+1234567890" --email "john@example.com" \
  --org "Acme Corp" -o contact.png

# Generate WiFi QR code
cargo run -p qr-cli -- wifi \
  --ssid "MyNetwork" --password "secret123" \
  --encryption wpa -o wifi.png

# Generate email QR code
cargo run -p qr-cli -- email "hello@example.com" \
  --subject "Hello" --body "Nice to meet you" \
  -o email.png

# Generate with logo overlay
cargo run -p qr-cli -- url "https://example.com" \
  --logo ./logo.png --logo-size 25 --ec-level high \
  -o branded-qr.png

# Bulk generation from JSON file
cargo run -p qr-cli -- bulk items.json --output-dir ./output/

# Bulk generation as ZIP
cargo run -p qr-cli -- bulk items.json --zip --output-dir ./output/

Configuration

All configuration is via environment variables. No .env file is required for local development — all values have sensible defaults.

Variable Default Description
HOST 0.0.0.0 Server bind address
PORT 3000 Server port
RUST_LOG info Log level (trace, debug, info, warn, error)
API_KEYS (empty) Comma-separated API keys. Auth is disabled when empty.
RATE_LIMIT_PER_MINUTE 60 Max requests per minute per IP
MAX_BODY_SIZE 10485760 Maximum request body size in bytes (10MB)
CORS_ORIGINS * Allowed CORS origins (comma-separated, or * for all)
FRONTEND_DIR ./frontend/dist Path to built frontend static files

Local Development

No configuration needed. Just run:

cargo run -p qr-api

Production

Create a .env file or set environment variables:

cp .env.example .env

Recommended production settings:

# Enable authentication
API_KEYS=your-secure-key-1,your-secure-key-2

# Adjust rate limit
RATE_LIMIT_PER_MINUTE=120

# Structured logging
RUST_LOG=info

When API_KEYS is set, all /api/* endpoints require authentication via:

  • Header: Authorization: Bearer <your-api-key>
  • Query param: ?api_key=<your-api-key>

The following endpoints are always public (no auth required):

  • GET /health
  • GET /api/docs (Swagger UI)
  • GET / (frontend)

API Reference

Method Endpoint Description Auth
GET /health Health check ({"status":"ok","version":"0.1.0"}) No
POST /api/generate Generate QR code → binary image download Yes*
POST /api/generate/base64 Generate QR code → JSON with base64 data URI Yes*
POST /api/bulk Bulk generate → ZIP archive download Yes*
GET /api/docs Swagger UI (interactive API documentation) No
GET /api-docs/openapi.json Raw OpenAPI specification No
GET / Web frontend (SolidJS SPA) No

*Auth required only when API_KEYS is configured.

Content Types

// URL
{"type": "Url", "data": "https://example.com"}

// Plain text
{"type": "Text", "data": "Hello, World!"}

// vCard contact
{"type": "VCard", "data": {
  "first_name": "John",
  "last_name": "Doe",
  "organization": "Acme Corp",
  "title": "Engineer",
  "phone": "+1234567890",
  "email": "john@example.com",
  "website": "https://example.com",
  "address": "123 Main St"
}}

// WiFi network
{"type": "WiFi", "data": {
  "ssid": "NetworkName",
  "encryption": "WPA",
  "password": "secret123",
  "hidden": false
}}

// Email
{"type": "Email", "data": {
  "to": "hello@example.com",
  "subject": "Hello",
  "body": "Message body"
}}

Style Options

Field Type Default Description
size integer 512 Output image size in pixels (64–4096)
foreground_color string "#000000" QR module color (hex)
background_color string "#FFFFFF" Background color (hex)
quiet_zone integer 2 Margin in modules (0–10)
logo_base64 string null Base64-encoded logo image
logo_size_percent integer 20 Logo size as % of QR code (1–40)

Output Formats

Value MIME Type Extension
Png image/png .png
Svg image/svg+xml .svg
Jpeg image/jpeg .jpg

Error Correction Levels

Value Recovery Best For
Low ~7% Maximum data density
Medium ~15% General use (default)
Quartile ~25% Moderate error tolerance
High ~30% Logo embedding, printed QR codes

Postman Collection

A ready-to-use Postman collection is included at postman/QR_Code_Generator_API.postman_collection.json.

Importing into Postman

  1. Open Postman
  2. Click Import (top-left)
  3. Select the file postman/QR_Code_Generator_API.postman_collection.json
  4. The collection will appear in your sidebar

Collection Contents

The collection includes 17 pre-built requests organized into folders:

Folder Requests Description
Health 1 Health check endpoint
Generate — Single QR Code 10 URL, Text, vCard, WiFi, Email, custom colors, SVG format, minimal request, high EC
Bulk Generation 2 Multiple URLs, mixed content types
Error Cases 4 Invalid URL, empty content, invalid email, empty bulk request

Collection Variables

After importing, set these variables in the collection settings:

Variable Default Description
base_url http://localhost:3000 Server URL. Change for staging/production.
api_key (empty) Your API key. Leave empty if auth is disabled on the server.

Every request inherits Bearer token auth from the collection level, so setting api_key once applies to all requests automatically.


CLI Reference

qr-cli <COMMAND>

Commands:
  url    Generate a QR code from a URL
  text   Generate a QR code from plain text
  vcard  Generate a QR code from vCard contact info
  wifi   Generate a QR code for WiFi network
  email  Generate a QR code for an email
  bulk   Generate multiple QR codes from a JSON file
  help   Print this message or the help of the given subcommand(s)

Shared Options (available on all single-generation commands)

Option Short Default Description
--output -o qrcode.png Output file path
--format -f png Output format: png, svg, jpeg
--size -s 512 Image size in pixels
--fg-color #000000 Foreground color (hex)
--bg-color #FFFFFF Background color (hex)
--ec-level medium Error correction: low, medium, quartile, high
--quiet-zone 2 Quiet zone margin (modules)
--logo Path to logo image file
--logo-size 20 Logo size as percentage (1–40)

Architecture

┌─────────────────────────────────────────────────────┐
│                  Docker Container                    │
│                                                      │
│  ┌────────────┐    ┌─────────────────────────────┐  │
│  │  SolidJS   │    │      Rust (Axum) API        │  │
│  │  Frontend  ├───►│                             │  │
│  │  (static)  │    │  ┌───────────────────────┐  │  │
│  └────────────┘    │  │      qr-core lib      │  │  │
│                    │  │  (stateless engine)    │  │  │
│                    │  └───────────────────────┘  │  │
│                    │                             │  │
│                    │  Middleware:                 │  │
│                    │  ├── CORS                   │  │
│                    │  ├── API key auth           │  │
│                    │  ├── Rate limiting (in-mem) │  │
│                    │  └── Request tracing        │  │
│                    │                             │  │
│                    │  Config: env vars            │  │
│                    └─────────────────────────────┘  │
│                                                      │
│              [ Fully stateless — no database ]        │
└─────────────────────────────────────────────────────┘

The project uses a Cargo workspace with three crates:

  • qr-core — Pure library crate. Contains all QR generation logic, content type encoding, styling, logo overlay, and bulk ZIP creation. Zero framework dependencies. Can be used independently.
  • qr-api — Binary crate. Axum web server that exposes qr-core as a REST API. Handles authentication, rate limiting, CORS, request validation, and serves the frontend.
  • qr-cli — Binary crate. Clap-based command-line tool that calls qr-core directly. No network dependency.

The Docker build is a 3-stage process:

  1. Frontend builder (Bun) — installs dependencies and builds the SolidJS app
  2. Rust builder — compiles both binaries in release mode with dependency caching
  3. Runtime (Debian slim) — copies only the binaries and static files (~50–80MB final image)

Roadmap

Future additions that can be built on top of this foundation:

  • Analytics / scan tracking — SQLite-backed redirect endpoint to count QR scans
  • Short URL integration — Shorten URLs before encoding to reduce QR complexity
  • Template styles — Rounded modules, dot patterns, gradient fills
  • QR code reader — Decode uploaded QR code images
  • Batch CSV import — Upload a CSV file for bulk generation in the web UI
  • Download history — Track recently generated QR codes (browser local storage)
  • API usage dashboard — Per-key usage metrics and quota tracking
  • Integration tests — Comprehensive test suite for core library and API

License

MIT

About

Full-stack web application for generating and managing qr-code generation with customizable options for different usecases

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published