glyphbyte

One drawn glyph is one byte.

Draw the first bytes of a nostr event id or pubkey on any surface with any pen, chalk or mower. Each byte is a square frame holding one of sixteen upright icons and up to four corner dots: the icon is the first hex digit, the dots are the second. A phone reads the row back on the device, and a relay resolves the bytes to the event or the profile they name.

How it works

  1. Draw

    Take the first six bytes of an id or a pubkey. For each byte draw a square frame, the icon for its first hex digit upright in the middle, and the dots for its second hex digit in the corners. Draw them left to right, underline the whole row, and put a fat dot at the start of the line.

    Six framed glyphs in a row above an underline that starts with a fat dot
    e8ed3798c6ff as the reference renderer draws it, one byte per frame:
    1. e8 star, dot top-left
    2. ed star, dots top-left, top-right, bottom-left
    3. 37 moon, dots top-right, bottom-right, bottom-left
    4. 98 tree, dot top-left
    5. c6 x, dots top-right, bottom-right
    6. ff fish, dots top-left, top-right, bottom-right, bottom-left
  2. Read

    Open the reader on a phone and take a photo. It finds the frames, the underline and the dot, straightens each frame, and reads the icon and each corner dot with a small neural network, all in JavaScript on the device. The underline tells it which way is up, and the icons check it: each has a top, so a photo taken sideways or upside down reads the same, even without an underline.

    Where a glyph is unclear the reader keeps the alternatives instead of guessing, and returns the most probable whole readings, ranked. A missing glyph is never dropped silently, because that would shift every byte after it.

  3. Look up

    The bytes are a prefix. The reader asks a relay for every candidate reading at once, as an event id prefix and as a pubkey prefix, and shows what comes back with the author's profile. You confirm which one you meant. A wrong candidate matches nothing, which is why there is no checksum.

How well does it work

On the synthetic benchmark in BENCH.md (200 scenes of pen and marker drawings with random handwriting severity, perspective, any camera roll, lighting, blur and JPEG on photographed backdrops) the reference reader finds 89% of the frames, reads 95% of the bytes correctly where the frame count matched, and gets the whole row right as its first answer 63% of the time; the smaller model that runs in the browser gets 62%. With chalk on pavement and paths in crop fields mixed in, whole rows drop to 45%: grainy strokes still break frames apart. Real handwriting so far: rows in coloured chalk on a sidewalk read exactly, found by their colour where in gray they barely differ from the concrete. Faint chalk whose colour differs from the surface but whose brightness does not, and rows drawn in two colours, are still weak, and that is the next thing to improve.

The alphabet

hexiconhexicon
0house8pie
1heart9tree
2dropaplus
3moonbflag
4crowncx
5arrowdbolt
6boxestar
7triangleffish

The second hex digit is the sum of the corner dots, clockwise from the top-left: 8 top-left, 4 top-right, 2 bottom-right, 1 bottom-left. So e8 is a star with one dot top-left, 50 an arrow with no dots, ff a fish with all four. Sixteen icons times sixteen dot patterns is 256: every byte is exactly one drawing.

The GlyphByte sheet: all 256 glyphs, sixteen icons down, sixteen dot patterns across
All 256 glyphs. The row is the icon, the first hex digit; the column is the dots, the second.

Rows in the first alphabet (format 1, 2026-09-22: sixteen pictograms, rotated, outline or filled, in square or circle frames) still read: the reader tries both formats on every photo and says which one it found. The reader's glyph switch still draws format 1, and its sheet is here.

Draw a row

Look it up

The reader sends every candidate reading in one request, as an ids prefix and as an authors prefix for kind 0 profiles:

["REQ", "gb", {"ids": ["e8ed3798c6ff"]}, {"authors": ["e8ed3798c6ff"], "kinds": [0]}]

Prefix matching in ids and authors was part of the first NIP-01 and was later removed from the text, so it needs a relay that still supports it. As of 2026-09 grain honours prefixes of any length in both fields; strfry and khatru currently do not (strfry answers CLOSED, khatru returns nothing). The reader defaults to wss://wheat.oslim.dev, a grain relay, and tests whichever relay you enter once, by fetching one event and asking for it again by an 8-character prefix, then tells you when a relay rejects or ignores partial queries.

Results show the author's profile and which candidate they matched, and the person confirms which one they meant. A prefix is a pointer, not a proof: the resolved full id or pubkey is the reference, never the drawn bytes.

Get it

The whole reader runs in the browser: the detector, the network weights and the icon shapes are inline in one page, and nothing leaves the device except the relay queries you can see on the page, and what you publish. The same file is also a napplet (NIP-5D) that a nostr shell can load in a sandboxed iframe.