DEV Community

How I Built a Browser-Based Batch QR Code Generator for 1,000 Items

Creating one QR code is easy. Creating hundreds of different codes for event badges, inventory labels, restaurant tables, or classroom materials is a workflow problem. I recently built a browser-based batch QR workflow for ZapQR.

The goal was simple:

  • accept manual lines, CSV, Excel, or TXT input
  • generate up to 1,000 static QR codes in one batch
  • apply one design consistently across the batch
  • export PNG, JPG, or SVG files
  • preserve the mapping between every source value and generated image
  • package the result as a ZIP
  • require no account and no server-side batch upload

This article explains the decisions behind that workflow, the edge cases that mattered, and why I kept static batch generation separate from Dynamic QR.

Disclosure: I build ZapQR. This is an engineering walkthrough of a real product feature, not an independent product review.

The real problem is not QR generation

A QR library can turn one string into one image quickly. The harder problem begins when the input is a spreadsheet with hundreds of rows. A useful batch generator has to answer questions such as:

  • What counts as one item?
  • How should empty rows be handled?
  • How do users verify which image belongs to which input?
  • What happens when an Excel workbook contains multiple sheets?
  • How do we keep the interface responsive while generating hundreds of files?
  • How do we prevent a large batch from exhausting browser memory?
  • Which export format should be used for print?

The implementation therefore became a data pipeline rather than a larger version of a single-code form.

The browser-side pipeline

The workflow can be summarized as:

Manual lines / CSV / Excel / TXT
โ†“
Parse and normalize values
โ†“
Remove empty or unusable entries
โ†“
Enforce the 1,000-item limit
โ†“
Generate one static QR per item
โ†“
Render PNG, JPG, or SVG
โ†“
Build indexes and a README file
โ†“
Package as ZIP

Keeping this pipeline in the browser was an intentional product boundary. For static QR codes, each image contains the final value directly. There is no technical need to send a spreadsheet to a server just to convert its rows into images. Local processing also means users can test the tool without creating an account or waiting for a remote job queue.

You can try the finished workflow in the ZapQR batch QR code generator.

Normalizing different input formats

The generator accepts four input paths:

Manual lines - The simplest format is one URL, label, SKU, or text value per line. Blank lines are ignored, and the remaining values preserve their original order.

CSV - CSV is useful for exports from spreadsheets, databases, forms, and inventory systems. A single content column is the easiest structure to audit, but real-world CSV files often contain extra empty cells or headings, so normalization is necessary.

Excel - Excel support uses the first worksheet and reads non-empty values. The important design decision is to make the transformation predictable: one non-empty value becomes one QR code, in a stable order.

TXT - TXT is effectively the portable version of manual input. It works well when another system already exports one value per line.

All four paths eventually produce the same normalized array. After that point, the QR rendering code does not need to know where the input came from.

Why the limit is 1,000 items

A browser can generate far more than 1,000 simple QR codes, but a product limit should be based on the complete workflow, not only the QR algorithm. Each item may require:

  • QR matrix generation
  • canvas or SVG rendering
  • optional colors, shapes, margins, and a center logo
  • conversion into a downloadable file
  • temporary in-memory storage
  • inclusion in a ZIP archive
  • an index entry

Those costs multiply quickly, especially for large raster images. A 1,000-item cap keeps the workflow useful while placing a clear ceiling on memory usage and waiting time. The UI also exposes progress and cancellation. Long-running work should never feel like a frozen page, and users need a safe way to stop a batch before export completes.

One design configuration, many outputs

Batch generation becomes much easier to reason about when design settings are shared across the batch. The user chooses settings such as:

  • output size
  • foreground and background colors
  • error correction
  • quiet-zone margin
  • supported body and finder shapes
  • optional center logo
  • PNG, JPG, or SVG output

Those choices are applied consistently to every generated image. This is more predictable than maintaining hundreds of independent design states. It also matches real use cases: event badges, product labels, and classroom cards generally need a consistent visual system.

PNG, JPG, or SVG?

The three formats solve different downstream problems.

PNG - PNG is the practical default for documents, websites, slide decks, and most fixed-size print layouts. It preserves sharp edges without JPEG compression artifacts.

JPG - JPG is available for workflows that specifically require JPEG files. Because JPEG has no transparency, the output needs a solid background.

SVG - SVG is the best choice when a designer needs to resize codes for packaging, signs, or professional print layouts. The code remains sharp because it is represented as vector geometry.

Regardless of format, the final printed version should be scan-tested. A technically valid image can still fail after being resized too small, printed with weak contrast, or placed on a reflective surface.

The ZIP needs more than images

A folder containing qr-001.png through qr-500.png is not enough. Without an index, the recipient cannot reliably tell which source value produced which file. The batch ZIP therefore includes:

  • an images folder with numbered QR files
  • index.csv
  • index.txt
  • index.html
  • README.txt

The numbered filenames preserve the source order, while the index files make the output auditable in spreadsheets, text editors, and browsers. This small decision turns a collection of images into a usable handoff artifact.

Static batch QR and Dynamic QR are different products

Static batch codes directly contain their final URL or text. If the destination changes after printing, the code must be regenerated and reprinted. Dynamic QR codes contain a stable short link. The server resolves that short link to the current destination, which makes post-print editing and scan tracking possible.

That difference affects architecture:

Concern Static batch QR Dynamic QR
Account required No Yes
Destination stored by ZapQR No Yes
Edit after printing No Yes
ZapQR scan tracking No Yes
Server redirect No Yes

I kept these workflows separate because combining them would make the static tool less private and more complicated. Users who only need final, fixed codes should not be forced into an account-based redirect system. For printed campaigns whose destination may change, the separate Dynamic QR Code Generator is the appropriate workflow.

Lessons from building it

The most useful lessons were not about drawing QR modules.

  • Normalize early. Convert every input format into one predictable internal representation.
  • Preserve source order. Users need to map generated files back to spreadsheet rows.
  • Set a product limit around the whole workflow. Rendering and ZIP creation matter more than raw string-to-QR speed.
  • Make long work observable. Progress and cancellation are product features, not polish.
  • Export an audit trail. Index files are as important as the images.
  • Keep static and dynamic architecture separate. They have different privacy, storage, and reliability tradeoffs.
  • Test the physical output. Browser success is not the same as print success.

Closing thoughts

Batch tools are valuable because they remove repetitive work, but reliable batch tools also need predictable data handling, visible progress, bounded resource usage, and output that another person can audit. The implementation now powers ZapQR's free batch workflow for up to 1,000 static codes.

If you are building a similar browser-side generator, I would be interested to hear how you handle large exports, cancellation, and source-to-file mapping. Try the workflow on ZapQR, and scan-test a few outputs before committing a large print run.

Comments

No comments yet. Start the discussion.