TLcube

QR reads well.
It has just never been pretty

True 3D H cube code on the transparency checkerboard — go to the H card

Posters, packaging, business cards — QR is everywhere, and dropping a black-and-white square onto a design you spent weeks on has always stung. But QR looks the way it does for a reason: it is what you build when a 1994 camera and 1994 silicon have to read it at all.

Those constraints have largely lifted. Phone cameras and compute have room to spare now. So instead of chasing recognition alone, we spent that headroom on being worth looking at. This is not a replacement for QR — it is a seat next to it. The result is a 3D barcode — printed flat, but read as solid.

Types

Pick by where it will sit. The planar types share one data contract and differ only in silhouette; True 3D H is the Y group’s physical cube extension, with a format of its own. Every code below encodes https://tl.estre.so.

Type Y — single cube

Type Y — single cube

Three n×n faces. A single solid mark, good for signage and merch.

n = 13 / 21 / 25 · net payload 31 / 98 / 141 B

True 3D H — the Y group’s physical cube extension

Its own format for a real cube, with different data on 1…6 faces. The generator also exports a rotation video (MP4), paper patterns and 3D-print files.

H0…H8 · n = 13…45 · net payload 3 faces 3…333 B · 6 faces 6…666 B (ECC-M, 3 tones)
Type O — hex field

Type O — hex field

The base form. Rhombic cells tile outward from a central finder.

k = 6 / 8 / 10 / 12 · net payload 18 / 39 / 65 / 97 B
Type C — notched ultra-capacity

Type C — notched ultra-capacity

The 3 o’clock notch fixes both orientation and type in the silhouette. C0–C3 are for close-range scanning; bring C1 and above closer or zoom in.

k = 14 / 16 / 18 / 20 · net payload 130 / 172 / 220 / 255 B
Type A — triangular silhouette

Type A — triangular silhouette

A hexagonal core plus corner patches, forming an equilateral triangle.

k = 6 / 8 / 10 · net payload 31 / 62 / 101 B
Type K — Hexagram

Type K — Hexagram

A triangle unioned with its 180° image. Largest payload at the same k.

k = 6 / 8 / 10 · net payload 43 / 86 / 138 B

Net payload is at ECC-M. Every type, H included, can carry a fallback QR alongside, so there is still a path where a TL code cannot be read. H places it in the top-left corner by default.

Why now

QR was the right answer for its moment. Two values, square modules, big finder patterns — every one of those choices existed so a weak camera could still read it. Under those constraints, giving up on looks was rational.

That premise changed. Phone cameras today are nothing like those, and real-time video processing runs inside a browser. So the headroom could go into density — or it could go into how it looks. That is why this exists.

Density was the trade. Rhombic cells are less area-efficient than square modules. This format does not compete on density. If you need to carry a lot, QR is the right tool.

How it works

1. Cell = three rhombi

A rhombille tiling splits each hexagonal cell into T, L and R faces.

2. Order = symbol

Ranking the three luminances gives 3! = 6 outcomes — one base-6 digit.

3. 3 digits = 1 symbol

Reed–Solomon over the prime field GF(211) corrects errors.

What this frees up

Invariant under monotonic transforms. Global lighting shifts, gamma, and printer tone mapping are monotonic — they cannot change an ordering. If the order survives, the value survives.

The renderer stays free. The data contract is only "the order between faces, plus a minimum separation". Inside that, colour, texture, per-face gradients and animation are all open. That freedom is the point of the format.

It does not make anything pretty on its own. What opens up is the contract, not the outcome. What you draw inside it is still your work.

Scanner — where it stands

The decoder works. All four types read from real-device photos; what is left is raising accuracy and speed. Each time below is one decode of one static photo taken on a real phone — not time to first lock or a live success rate.

TypeReal photos decodedOne static-photo decodeLive validation
Type Y — single cube9 / 16~1.8 smore data needed
Type O — hex field29 / 48~1.9 smore data needed
Type A — triangular silhouette18 / 19~2.4 smore data needed
Type K — hexagram18 / 27~3.1 smore data needed
Centre-QR variant (all four types) · 2026-08-138 / 9—more data needed

One decode of one still photo. Type O is now the fastest; A, K and Y sit close together behind it. ⚠ An earlier version of this page said Type Y was the fastest — that was a 9-photo sample, and on a wider sample the order flipped. Do not read these as live first-lock times.

One static-photo decode time does not predict how live scanning feels. In the first real-device lab trace, a fast frame could still lead to a slow first lock when many frames were needed before one succeeded, and the type ranking differed from this static-photo table. That trace covers one device and a small sample, so we do not assign live usability grades yet.

Shooting conditions matter too. Measured, 9 pixels per cell was the decode floor, and at the same distance an ultra-wide lens frames the code smaller and drops below that line (ultra-wide 7.6 px failed / wide 9.1 px succeeded). That is why the scanner offers a lens picker.

In the centre-QR variant, a QR block replaces the central finder. Its finder patterns provide the position and orientation entry point used to decode the surrounding TL body. By default the QR remains a reader-link fallback; the payload stays in the TL body. Since 2026-08-28 the generator’s default for Types O, C, A and K is the Centre TL finder with an outer fallback QR in the top-left corner; centre QR remains one of the finder choices. The centre-QR row in the table above measures that variant (2026-08-13 round).

Type C and True 3D H are not in the table above, and H’s camera recognition rates and FPS are not guaranteed. The scanner has two engines: R1 reads planar TL types one frame at a time, and R2, the default, collects Type Y and H across frames. For H it releases a result only after the required faces pass RS/CRC checks. In browsers with BarcodeDetector, R2 also reads ordinary QR codes; a link read from a QR code is never opened automatically — check the address, then tap it.

Measured 2026-08-27 · sample of 110 photos (each tried at 960 · 1440 px short side). ⚠ Most of the sample is photographed off a monitor, so these are not print or in-situ numbers. And 123 of the 233 corpus frames are limit/experiment shots kept precisely because they do not decode yet — they are excluded here. Only the centre-QR row is from the older 2026-08-13 round.

Spec and implementation

The format spec and reference implementation are published under the Apache License 2.0. Vanilla JavaScript, in-repository Node.js build scripts, zero runtime dependencies — it runs as a single HTML file.

Implementing only the decoder counts as a conforming implementation. Adoption starts with the reading side.

SiteRoleState
tlcube.estre.soGeneratorlive
tlscan.estre.soScannerlive — status ›
tl.estre.soOverview hubyou are here