Skip to main content
Glama
open-qr

OpenQR

Official
by open-qr
README.md
# OpenQR

**Free, open-source, watermark-free QR code generator.** Runs entirely in your
browser — no tracking, no sign-up, no limits.

[![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-07B1B0.svg)](LICENSE)
![Next.js](https://img.shields.io/badge/Next.js-16-232E3A)
![No watermark](https://img.shields.io/badge/watermark-none-07B1B0)
[![Listed on mcpservers.org](https://mcpservers.org/badge.svg)](https://mcpservers.org/servers/openqr-mcp)

Most online QR generators bait you with "free" and then add a watermark, cap your
download size, hide vector export behind a paywall, or route your code through
*their* servers so it dies when you stop paying. A QR code is just an open
standard (ISO/IEC 18004) that costs nothing to generate. **OpenQR keeps it that way.**

This repository is the **basic generator tool** — the reference open-source
implementation. It is deliberately small and easy to fork.

If OpenQR is useful to you, a star on the repository helps other
people find it. That is the whole ask.

## Hosted version: free API, MCP server and editable codes

Everything in this repo is and stays free, with no watermark and no expiry. The
hosted build at **[openqr.uk](https://openqr.uk)** adds an *optional* account layer
for people who want editable codes and automation:

- **Dynamic / editable QR codes** with scan analytics. Change the destination after
  you've printed it. **1 free** on a free account (7 days of scans by country);
  **25 editable codes** on Pro at £9/month or £90/year, which also unlocks a 90-day
  scan-analytics window plus town and region detail, device and referrer breakdowns
  with CSV export, a branded subdomain, and password-protected codes.
  Existing subscribers keep their current plan and price.
- **Free REST API.** Generate codes and manage dynamic codes programmatically.
  OpenAPI spec at [`/openapi.json`](https://openqr.uk/openapi.json); interactive docs
  at **[openqr.uk/api](https://openqr.uk/api)**.
- **Hosted MCP server** at `https://openqr.uk/mcp` (Streamable HTTP).
  Generate and manage QR codes directly from Claude, Cursor or any MCP client. Listed
  in the [official MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=openqr).
  Remote-capable clients connect to that URL directly; stdio-only clients can
  bridge to it with `npx -y @open-qr/mcp` and `OPENQR_API_KEY` set
  ([details](./mcp/)).

The static generator in this repository never calls any of that. It stays 100%
client-side (see [Privacy](#privacy)), and none of it is required to use or
self-host the generator.

### Connecting an MCP client

Get a free key at [openqr.uk/api](https://openqr.uk/api), then point your client
at the server with the key as an auth header.

Claude Code:

```bash
claude mcp add --transport http openqr https://openqr.uk/mcp \
  --header "Authorization: Bearer oqr_YOUR_KEY"
```

Cursor (`~/.cursor/mcp.json`), and any other client that speaks Streamable HTTP:

```json
{
  "mcpServers": {
    "openqr": {
      "url": "https://openqr.uk/mcp",
      "headers": {
        "Authorization": "Bearer oqr_YOUR_KEY"
      }
    }
  }
}
```

## Tools

The hosted MCP server at `https://openqr.uk/mcp` exposes these tools (run `tools/list` for the live set). **Every tool
requires a free API key** — create one at [openqr.uk/api](https://openqr.uk/api) and pass
it as `Authorization: Bearer oqr_...` on the MCP connection.

| Tool | What it does |
| --- | --- |
| `generate_qr` | Generate a static QR code from any text or URL. Returns a PNG image or SVG markup. |
| `create_dynamic_qr` | Create an editable QR code whose destination you can change later without reprinting. |
| `update_dynamic_qr` | Change a dynamic code's destination, label, custom short link, tags or folder. |
| `get_dynamic_qr` | Get one code's full details: destination, short link, label, type, tags, folder, status, created date. |
| `get_scans` | Scan statistics for a dynamic code. |
| `list_dynamic_qr` | List your dynamic codes with id, short URL, destination, label and status. |
| `delete_dynamic_qr` | Permanently delete a dynamic code. Its short link stops working. |
| `bulk_create_dynamic_qr` | Create up to 200 dynamic codes at once. |
| `list_folders` | List your folders. |
| `create_folder` | Create a folder to organise codes. |
| `delete_folder` | Delete a folder. Its codes are un-filed, not deleted. |
| `list_themes` | List saved style themes. Apply one by passing its id or name as `theme`. |
| `create_theme` | Save a reusable style theme (colours, dot and corner styles). |
| `delete_theme` | Delete a saved theme. Codes already styled with it keep their look. |
| `get_subdomain` | Show the branded subdomain on the account, and whether it is suspended. |
| `set_subdomain` | Claim or change the branded subdomain so codes also resolve at `{name}.oqr.to`. Pro only. |
| `clear_subdomain` | Release the branded subdomain. Codes stay live on the plain short link. |

It also exposes **5 resources** and **4 prompts**:

- **Resources** are built-in QR style presets at `openqr://preset/classic`, `/teal`,
  `/high-contrast`, `/dots` and `/classy`. Read one and pass its style to `create_theme`.
- **Prompts** are `create_tracked_qr`, `bulk_qr_for_print`, `brand_a_qr` and `qr_scan_report`.

## Features

- **No watermarks, no size limits, no sign-up** — every feature is free
- **Private by design** — codes are generated entirely in your browser; the content never touches a server
- **Export anywhere** — PNG / WebP up to 4096px, plus true-vector **SVG** and **PDF**
- **Full styling** — colours, gradients, dot & corner styles, logo embedding, "Scan me" frames
- **Smart input** — paste a link or text and the type is auto-detected
- **Rich payloads** — URL, text, email, phone, SMS, WhatsApp, Wi-Fi, and a map-based location picker
- One-click copy, shareable design links, light/dark, responsive, keyboard-accessible

## Quick start

```bash
pnpm install
pnpm dev        # http://localhost:3011
```

## Build & self-host

```bash
pnpm build
pnpm start      # serves on :3011 (standalone output)
```

It's a standard Next.js app — host it anywhere (a VPS, a Raspberry Pi, Cloudflare,
behind any reverse proxy). It needs **no environment variables, no database, no
secrets** to run. The dev/start scripts above use port **3011**; the Docker
image below serves on **3000**. The only configuration either way is `PORT`.

## Deploy (Docker image)

A multi-arch image (`linux/amd64`, `linux/arm64`) is published to GHCR on every
release tag:

```bash
docker run -d --name openqr --restart unless-stopped -p 3000:3000 ghcr.io/open-qr/openqr:latest
```

Or with [`docker-compose.yml`](./docker-compose.yml):

```bash
docker compose up -d          # update later: docker compose pull && docker compose up -d
```

Pin a version tag in production (`ghcr.io/open-qr/openqr:1.0.1`); `latest`
moves with every release. The container is a prebuilt, non-root standalone
server with a healthcheck, and carries `LICENSE` and `NOTICE` inside the image.

### One-click deploys

| Host | Link | Notes |
|---|---|---|
| [DigitalOcean App Platform](https://cloud.digitalocean.com/apps/new?repo=https://github.com/open-qr/openqr/tree/main) | 1-click button | Reads [`.do/deploy.template.yaml`](./.do/deploy.template.yaml); smallest instance, port 3000 |
| [Render](https://render.com/deploy?repo=https://github.com/open-qr/openqr) | Blueprint button | Reads [`render.yaml`](./render.yaml); assumes a paid instance (Render's free tier sleeps) |
| Koyeb | Deploys from the image | Any public `ghcr.io/open-qr/openqr` tag, no repo build |

Deploying through any of these adds no terms beyond AGPL-3.0: the source is
this repository, and the image carries the licence and third-party notices.

## Embedding

The `<Generator/>` component is self-contained and configurable:

```tsx
import { Generator } from "@/components/generator/generator";

// Full page (default OpenQR logo header):
<Generator />

// Embedded widget, your own branding, no default header:
<Generator embedded header={<MyLogo />} />

// Inject your own post-download call-to-action:
<Generator renderSuccess={(variant) => <MySupportCluster variant={variant} />} />
```

The tool ships **zero analytics**. If you want anonymous UI events (e.g. which
export format was used — never the QR content), inject a handler:

```ts
import { setTrackHandler } from "@/lib/analytics";
setTrackHandler((action, name, category) => myAnalytics.track(category, action, name));
```

## Privacy

QR generation happens 100% in your browser. The only optional outbound calls are
in the **Location** tool: map tiles from CARTO and address lookups via
OpenStreetMap's Nominatim. Nothing else leaves the device.

## Tech stack

Next.js 16 (App Router) · React 19 · TypeScript (strict) · Tailwind v4 ·
[`qr-code-styling`](https://github.com/kozakdenys/qr-code-styling) · Leaflet · pnpm.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md). Keep it simple, accessible, client-side,
and free — no feature should ever require payment to remove a watermark or unlock
a format.

## Licence

[AGPL-3.0](LICENSE) © 2026 Sam Moreton.

You're free to use, study, modify, self-host, and redistribute OpenQR under the
AGPL-3.0. If you run a modified version as a network service, the AGPL requires
you to make your source available under the same licence. If that doesn't suit
your use case, a **commercial licence** is available — see [NOTICE](NOTICE).