QR Code Studio: open-source QR generation with an API agents can actually use

QR Code Studio: open-source QR generation with an API agents can actually use

The real impetus was not a roadmap item. Mark posted on X the night we shipped:

Wife does a lot of flyers for her new job. All the ones she pulled up on the app store were ad-infested slop. I built a super simple QR code generator for her. And because I'm mister overkill, built an API, agents.md file and an SMCP plugin for it, too.

That is the honest origin story. A person making flyers needed a QR code without downloading spyware cosplaying as a utility. Everything else — open source, normalization, branded center logos, Kitchen POS pickup links — grew from "make the simple thing first, then stop lying to yourself about scope."

QR Code Studio lives at qr.decisionsciencecorp.com: browser studio for humans, REST API + PHP/Python SDKs + SMCP plugin + agents.md for everyone who cannot use the App Store version. Code is AGPL-3.0; docs are CC BY-SA 4.0 (COPYING.md). We published the repo in June 2026 because if we built it for family, we might as well ship it for strangers with the same ad-free constraint.

This post covers what we built after the flyer problem, why we open-sourced it, and how to integrate without reading three repos first.

Screenshots below are from the live site at qr.decisionsciencecorp.com — not mockups.

Live studio at qr.decisionsciencecorp.com — paste a URL, instant QR preview, download PNG or SVG. No ads, no App Store upsell.
Same live site catching a typo before print: alex@gnail.com surfaces a gmail.com suggestion — normalization is shared between browser and API.
DEV hub on the production host (/dev/) — API reference, SDK docs, and links to agents.md for humans and LLM hosts.
agents.md rendered on qr.decisionsciencecorp.com — the onboarding path we ship beside the README for Vernal and SMCP integrators.
Production studio on a phone-width viewport — flyer workflow without installing another adware app.

The problem with "just use a free QR site"

The App Store results Mark's wife tried are the consumer face of a deeper issue. Free generators are fine for one-off personal links. They are painful when:

  • Typos become permanent. Email domains and TLDs get mangled (concom, gnailgmail) at keyboard speed. Stickers do not have an undo button.
  • Agents cannot click. Vernal, Broca, and SMCP hosts need normalize → generate as HTTP or CLI — not "open this page in a browser."
  • Branding matters. Pickup windows and partner tables want a center logo on the code without breaking scan reliability.
  • Licensing is vague. We wanted code we could fork, self-host, and ship in client engagements without a terms-of-service archaeology project.

QR Code Studio is deliberately narrow: URLs, email, phone, plain text — validated, normalized, encoded. Not a marketing suite. Not a URL shortener. A tool that does one job honestly.

Two surfaces: browser studio and REST API

Browser studio (client-side)

The public page is a static studio: paste content, pick Auto/URL/Email/Phone, see a live preview, download PNG or SVG. Encoding runs in the browser via vendored qrcode-generator (MIT) — no round-trip required for casual use.

The studio shares the same normalization rules as the API. app.js and PHP QrNormalize are kept in semantic parity so "it looked fine in the browser" and "the API returned garbage" cannot diverge.

REST API (server-side)

For automation, batch jobs, and agents:

Endpoint Role
GET /api/v1/health.php Liveness + capability flags
POST /api/v1/normalize.php Validate, autocorrect, return encoded payload + suggestions
POST /api/v1/generate.php PNG or SVG bytes (base64 in JSON)
GET /api/v1/openapi.json Machine-readable contract

Quick start:

curl -sS https://qr.decisionsciencecorp.com/api/v1/health.php

curl -sS -X POST https://qr.decisionsciencecorp.com/api/v1/normalize.php \
  -H 'Content-Type: application/json' \
  -d '{"content":"hello@gnail.com"}'

curl -sS -X POST https://qr.decisionsciencecorp.com/api/v1/generate.php \
  -H 'Content-Type: application/json' \
  -d '{"content":"https://decisionsciencecorp.com","format":"png","ecl":"M"}'

PNG generation uses phpqrcode (LGPL) via PHP GD. SVG works without GD — useful on stripped-down dev hosts. OpenAPI documents error codes, optional X-API-Key auth, and rate limits (~120 req/min per IP on the public tier).

Normalization is the product

Anyone can draw black squares. The value is catching mistakes before they ship.

QrNormalize implements:

  • Scheme hints — bare domains get https:// suggested; mailto: and tel: for email/phone modes.
  • Email domain typos — Levenshtein-style fixes against a curated domain list (gmail.com, outlook.com, decisionsciencecorp.com, …).
  • TLD repairsconcom, ogorg, and other fat-finger patterns we have seen on real sticker orders.
  • Structured responsesencoded, type, optional suggestion + suggestion_reason so UIs and agents can ask "did you mean …?" instead of silently baking in the typo.

The API returns the same shape the browser uses. SDKs wrap it; the SMCP plugin wraps the SDK path. One normalization brain, three entrypoints.

Branded codes: center logo overlay

Commit 40640b0 added optional center logo overlay on generated PNG/SVG. Logos are base64 in the generate request; the renderer bumps error correction to at least Q when a logo is present so real-world scans stay reliable.

That matters for Empanada Empire pickup signage and partner materials — a plain black QR on a white label is fine for dev; affiliates want their mark in the center without hiring a designer for every window.

Agent integration: agents.md and SMCP

We ship agent onboarding the same way we ship human docs:

Resource URL
DEV hub qr.decisionsciencecorp.com/dev
agents.md live docs · GitHub
SMCP plugin smcp_plugin/qr_studio/cli.py --describe
PHP SDK sdk/php/QrStudioClient.php
Python SDK sdk/python/qr_studio/

Prefer SMCP when your host already runs Sanctum MCP plugins — health, normalize, generate, tool-help with discovery via --describe. Otherwise hit REST directly or import the SDK.

Optional server-side QR_STUDIO_API_KEY enables X-API-Key / Bearer for higher-trust deployments. Public tier is rate-limited per IP; AGPL source is on GitHub if you need a private instance.

Open-source slice (June 13)

The open-source release (e64cdbf) packaged:

  • AGPL API + shared PHP includes
  • Browser studio assets
  • DEV docs browser (markdown → HTML under /dev/)
  • SDKs and SMCP plugin in-repo
  • COPYING.md dual-license clarity (AGPL code, CC BY-SA docs)
  • Footer links to DEV hub and agent docs (57f05f6, 827b8a3)

Repo: github.com/decisionsciencecorp/qr.decisionsciencecorp.com

We are not pretending this is a venture-scale QR platform. It is production infrastructure we use — and we would rather maintain it in public than re-explain it on every engagement.

How we use it inside DSC

The flyer use case is still the spine — church bulletins, event handouts, wife's job materials. No ads, no upsell modal before download.

From there it spread into work we were already doing:

  • Empanada Empire — pickup URLs, partner customer links (empanadaempire.us/p/<slug>/), window signage.
  • Agent workflows — SMCP qr_studio__* tools for "generate a PNG for this URL" without browser automation.
  • Client deliverables — normalized email QR codes on conference badges, corrected before print.

If you only need one code once for a flyer, the browser studio is enough — that was the whole point of v1. If you need repeatable, testable, agent-callable QR generation, start at agents.md.

Deploy and ops

QR Code Studio runs on our multihost LEMP stack like sibling DSC properties. /root/sites/qr.decisionsciencecorp.com.env wires GitHub → sync.shdeploy.sh every few minutes — same cron pattern as Tasks and CRM. See docs/DEPLOY.md in the repo for the env template.

PHP GD must be enabled for PNG API output; SVG generation works without it. We keep db/.gitkeep so deploy rsync has a stable tree — the app is file-backed, not a heavy database product.

Health check for monitors:

curl -sS https://qr.decisionsciencecorp.com/api/v1/health.php | jq .

Design and quality bar

The studio uses the same dark DSC chrome as our other properties — compact hero, card-based input/preview grid, Inter typography. Playwright design smoke (tests/design_smoke.py) exercises Auto/URL/Email/Phone cases at mobile and desktop widths against a local php -S server.

API smoke (tests/api_smoke.py) and dev footer checks (dev_smoke.py) keep the OSS docs links from rotting — agents should always find agents.md from the live footer.

What we deliberately did not build

Out of scope Why
URL shortening / analytics Different product; use your own redirect layer
Dynamic QR redirect swaps Security and support burden
Account billing tiers Public + optional API key is enough for v1
Exotic payload types (WiFi, vCard) Maybe later; URL/email/tel cover our lab

Lessons for teams shipping small OSS utilities

  1. Ship for one real human first — a flyer deadline beats a architecture diagram every time.
  2. Normalize before encode — the bug is almost never the QR algorithm; it is the string fed into it.
  3. Ship agents.md beside README — the overkill phase is optional; the overkill phase is also how Otto stops asking you for PNGs.
  4. SMCP + REST + SDK — same three-layer pattern as Kitchen POS and Tasks; pick your transport.
  5. Dual license docs — AGPL code with CC BY-SA docs avoids "can we copy the tutorial into the client wiki?" fights.
  6. OpenAPI on day one — agents and humans both benefit from a single JSON contract.

QR Code Studio is live at qr.decisionsciencecorp.com. Questions, forks, and PRs welcome on GitHub — or contact us if you want help wiring it into a Sanctum agent stack.