QR Print Station is a self-hosted print intake server designed for local print shops. It replaces the counter handoff — customers scan a QR code posted anywhere in the shop, open a browser-based upload flow, attach their documents, set per-file print options (paper size, color mode, print style, copies), and submit their order without staff involvement. Staff then review, approve, and dispatch orders from a secret admin dashboard that is never exposed publicly. The entire system runs on your local network from a single Python process with no external dependencies beyond a MySQL database.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/hxmz-axfn07/qr-printing-sfw/llms.txt
Use this file to discover all available pages before exploring further.
Quickstart
Install, configure, and accept your first order in under 10 minutes.
Configuration
Environment variables, shop settings, pricing, and theme colors.
Admin Overview
Manage orders, review documents, and move jobs through the print queue.
API Overview
REST endpoints for orders, transitions, config, and file access.
System Architecture
QR Print Station is intentionally lightweight. The backend is a single Python file (server/app.py) built on top of the Python standard library’s http.server.ThreadingHTTPServer — there is no web framework. Static HTML and JavaScript in client/ are served directly by the same process, keeping deployment friction close to zero.
| Layer | Technology |
|---|---|
| HTTP server | Python http.server.ThreadingHTTPServer (stdlib) |
| Database | MySQL 5.7+ or MariaDB (via PyMySQL) |
| Frontend | Client-side HTML / vanilla JavaScript (client/) |
| QR code | qrcode[pil] — auto-generated PNG written to qr-codes/upload.png |
| Configuration | .env for server/DB settings; config.yml for shop content and pricing |
/upload route, and launches a background thread that re-checks and regenerates the QR every QR_REFRESH_SECONDS seconds. When a PUBLIC_URL (such as an ngrok tunnel) is set in .env, the QR code target switches to that URL automatically — the background thread detects the change and overwrites qr-codes/upload.png without a restart.
The Two Actors
Customers interact only with the public-facing side of the application:- They scan the QR code displayed in-shop or shared as a link.
- The browser opens the upload page where they enter their name, phone number, and any order notes.
- They add one or more files, then configure each document individually: paper size, color mode (black & white or color), print style (single- or double-sided), number of copies, and optional per-document notes.
- On submission they receive a success page showing their order ID.
/admin/<ADMIN_TOKEN>:
- Incoming orders appear with status
new. - Staff move each order through the workflow:
new → reviewing → ready → printing → printed. - From the dashboard they can search by order ID, customer name, or phone number; filter by status; view all uploaded documents; and open files directly in the browser.
- Orders can be cancelled (with a reason) at any active stage, or marked
failedif a print job goes wrong.
System Requirements
- Python 3.11 or later
- MySQL 5.7+ or MariaDB (any recent version)
- qrcode[pil] 8.2 — QR code image generation
- PyMySQL 1.1.1 — MySQL driver
- PyYAML 6.0.2 —
config.ymlparsing
requirements.txt and installed in one step during setup.
The admin dashboard is protected solely by a secret URL token — there is no username/password login screen. The
ADMIN_TOKEN value you set in .env is embedded directly in the URL path (/admin/<ADMIN_TOKEN>). For API calls the same token is accepted either as an X-Admin-Token request header or as a ?token= query parameter. Anyone who knows the token has full admin access, so it must be a long, random, unguessable string and should never be shared publicly or committed to version control. Change the default change-this-secret-token value before running the server on any network.