Every table in our database is inserted with the word "placeholder" in a NOT NULL column, because the QR code contains the row's own id
In PubTrivia a pub puts a printed code on each table. A team scans it, the phone opens a page, and they are in that night's quiz as that table. No app install, no account, which is the entire reason the product works in a room full of strangers. The feature page walks through what the player actually does , and the short version is that the code encodes a URL and nothing else:…
PubTrivia inserts the word "placeholder" into a NOT NULL column in each table of the database. This is because the QR code contains the row's own unique identifier. A team scans the code, and the phone opens a page, allowing them to participate in that night's quiz as that table. No app installation or account is required, which is the core reason the product functions in a room full of strangers.
The feature page explains how players actually engage with the product, and the brief version is that the code encodes a URL, with both the venue ID and table ID being UUIDs. The primary key for tableId is generated using Postgres' defaultRandom(). This creates a small and unintended ordering issue, as the image cannot be generated until the row exists, and the column holding the image is NOT NULL.
The solution is to insert a known-wrong value and immediately correct it after generating the QR code. The insert is performed for all tables simultaneously, generating IDs and returning them. Then, the codes are rendered and written in parallel. However, the insert and updates are not in one transaction, leading to rows with a literal "placeholder" value in the QR code URL.
If the process fails between these two statements, the issue arises, and the UI tries to render the image, which is not a valid PNG. The PNG size comparison shows that a real table URL is 101 characters, while the rendered data URL is 5,934 characters, about 4.3 KB of PNG once the base64 is undone. For a 50-table venue, this results in roughly 300 KB of base64 text in Postgres.
Although this is not free, the alternative is object storage, which would add more complexity, such as a bucket, public URL policy, cleanup job for orphaned objects, and a second thing that could fail while venues print their codes an hour before the quiz. Embedding the data URL offers the benefit of trivial consumption by all three consumers, including the dashboard card, download button, and print-everything button.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.