Skip to content
limitlessprojectsPublic

About

Every seed is a one-of-one poster. Deterministic generative SVG art from any phrase - pure Python, zero dependencies.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hapax

every seed is a one-of-one poster

deterministic generative SVG art from any phrase — pure Python, zero dependencies

python deps tests output license

hero

left to right: river sulking · low tide hum · warm front — all three live in gallery/


Type any phrase and hapax turns it into a poster: a deterministic, resolution-independent SVG you can print, pin, or set as a wallpaper. The same phrase always produces the same poster — byte for byte, on any machine, forever. Change one character and you get a completely different artwork that has never existed before and will never be generated again. That is why it is called hapax — from hapax legomenon, a word that occurs only once in a corpus.

There is no neural network here and no randomness that escapes you. Every "artistic decision" — the algorithm, the palette, the composition, the grain — is derived from the SHA-256 of your phrase through domain-separated random streams. The poster is not stored; it is recomputed from the seed each time, which means a poster is just its phrase.

quick start

git clone https://github.com/limitlessprojects/hapax.git
cd hapax
python hapax.py "a quiet machine"        # -> hapax-67dead9f.svg

That is the whole install. No pip, no venv, no build step — one file and the Python you already have. Open the SVG in any browser.

python hapax.py "torvalds" --style orbits --palette kiln     # pin the look
python hapax.py "sunday" --size 1920x1080                    # wallpaper, wide
python hapax.py "my saves" --sheet 12                        # 12 posters, one folder
python hapax.py --list                                       # see all styles/palettes

Omit the seed and hapax invents one and prints it back to you, so nothing is ever lost:

$ python hapax.py
hapax-3f9c21ab.svg  [mosaic/pastelex]  seed='untitled-4e81c2'

The seed that asked for this repo to exist — resolved to ribbons over a moss palette:

hapax "quantum" — ribbons/moss

"quantum" · ribbons/moss · 8fb7cf7a — one command, deterministic forever

make your own things

The examples/ folder is a set of ready pipelines that import hapax.py as a library — copy any of them and bend it to yours:

script what it does
examples/batch_from_file.py one poster per line of a phrases.txt — bulk editions
examples/wallpaper_pack.py one phrase → desktop / 4K / ultrawide / phone / tablet pack
examples/contact_sheet.py numbered edition #1..#N + a browsable index.html
examples/library_usage.py the full library API in ~40 lines — render, inspect, post-process

All four are pure standard library and read hapax from the repo root, so they run from anywhere:

python examples/wallpaper_pack.py "quantum" -o walls/
python examples/contact_sheet.py "album" -n 12 --style constellation

For anything beyond the flags, hapax.py is one readable file: a build_poster() pure function, a STYLES registry you can extend with your own drawing system, a PALETTES dict you can grow, and rng_for(seed, domain) if you want deterministic behavior in code of your own.

five algorithms

Every poster is one of five hand-built drawing systems. --style auto lets the seed choose.

flowfield

Thousands of particles advected through a seeded value-noise field, drawn as tapered ink strands over soft color washes. The signature style.

river sulking paper wind signal hum
"river sulking" "paper wind" "signal hum"

orbits

Concentric ring systems with dashed tracks, arc highlights and glowing planets — somewhere between an astronomical chart and a vinyl record.

low tide hum slow compass
"low tide hum" "slow compass"

constellation

A scatter of stars joined by proximity edges, with bright named stars, halos and a dashed sightline route. Faint survey grid underneath.

last bus map night shift
"last bus map" "night shift"

mosaic

Recursive rectangle subdivision with weighted fills, circle interrupts and ink leading — the poster behaves like a glazed tile wall.

brick garden
"brick garden"

ribbons

Layered cloth bands draped across the frame over a low sun — the loudest style.

warm front
"warm front"

twelve palettes

--palette auto picks one from the seed, or pin one by name:

argon kiln tide ember orchard monsoon candy noir paper signal moss pastelex

Each palette carries a background, an ink and six accents, tuned to work on dark and light ground — candy, paper and pastelex print on light, the rest glow on dark.

CLI reference

usage: hapax.py [-h] [-o OUT] [--style STYLE] [--palette PALETTE]
                [--size WxH] [--sheet N] [--no-grain] [--no-caption]
                [--list] [--quiet] [seed]

positional:
  seed                 any phrase; omit one to get a fresh random seed

options:
  -o, --out PATH       output path (default: hapax-<hash8>.svg)
  --style              auto | flowfield | orbits | mosaic | ribbons | constellation
  --palette            auto | argon kiln tide ember orchard monsoon
                             candy noir paper signal moss pastelex
  --size WxH           default 1200x1500 (4:5 poster)
  --sheet N            render N posters seeded "<seed> #1..N" into a folder
  --no-grain           skip the film-grain texture pass
  --no-caption         skip the edition caption
  --list               list styles and palettes
  --quiet              print nothing

Every poster carries a small edition caption — the seed, the style/palette and an 8-hex fingerprint — so any print can always be traced back to the exact phrase that made it.

how determinism works

One phrase goes in; five independent decisions come out. hapax hashes the seed with a domain tag into each subsystem, so the palette stream never knows what the layout stream is doing and tweaking one style never reshuffles the others:

def rng_for(seed, domain):
    h = hashlib.sha256(seed.encode() + b"\x1f" + domain.encode()).digest()
    return random.Random(int.from_bytes(h, "big"))

rng_for(seed, "choose-style")     # which algorithm
rng_for(seed, "choose-palette")   # which palette
rng_for(seed, "style:ribbons")    # that algorithm's entire layout
rng_for(seed, "grain")            # the grain pass

The RNG is Python's Mersenne Twister, seeded once per domain — and since the whole poster is a pure function of (seed, style, palette, size, grain, caption), the SVG you generate today is the SVG someone regenerates in ten years. The test suite asserts byte-equality across processes to prove it.

printing

SVG scales losslessly to any size. For paper:

# to PNG at 300 DPI (any of: resvg, inkscape, rsvg-convert, or just a browser screenshot)
resvg --width 3600 hapax-67dead9f.svg poster.png

For screens, generate at native resolution with --size 1920x1080 (desktop) or --size 1170x2532 (phone) — everything in hapax is drawn relative to the canvas.

license

MIT — see LICENSE. The tool is yours; every poster it makes is yours too.

About

Every seed is a one-of-one poster. Deterministic generative SVG art from any phrase - pure Python, zero dependencies.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages