URL parameters
All handled in the browser after mount, so they work on any deploy.
Content
| Parameter | Values | What it does |
|---|---|---|
r | base64 payload | Applies a shared recipe. Also loads a demo image so there is something to see it on |
recipe | preset name | Applies one of the 19 named presets, with that preset's own demo source |
project | project id | Opens a saved project. Checked first and wins over everything else |
demo | 1 | Loads a random background. Implied whenever r is present |
Purchase
| Parameter | Values | What it does |
|---|---|---|
buy | credits or pro | Resumes a purchase chosen on the pricing page |
qty | 20 to 300 | With buy=credits, the quantity |
cycle | monthly, quarterly, yearly | With buy=pro, the billing period |
These are stripped from the URL as soon as they are read, so a refresh or a bookmark cannot re-fire a purchase.
Other
| Parameter | Values | What it does |
|---|---|---|
settings | account, plan, credits, about | Opens settings on a section |
tour | 1 | Force-opens the welcome tour |
webgl | 1 | Opts into the instanced WebGL glyph renderer |
The pricing page also takes ?cycle= with the same three values, which preselects that
tab. /pricing?cycle=yearly is the link to send someone if you are quoting the yearly
price.
Building one
All of these hang off /app, and all are read after mount in the browser, so they
work on any deploy without server support.
| Goal | Link |
|---|---|
| Share a look | /app?r=<payload> |
| Share a named preset | /app?recipe=<name> |
| Open someone straight into a demo | /app?demo=1 |
| Send someone to the yearly price | /pricing?cycle=yearly |
| Open settings on the plan section | /app?settings=plan |
Precedence
When more than one content parameter is present, they do not merge. The order is:
- projectChecked first and wins outright. A saved project already contains a recipe and a source, so nothing else needs applying.
- rA shared recipe. Implies a demo source, so the look has something to sit on.
- recipeA named preset, with that preset's own demo source.
- demoJust a source, no look.
The purchase parameters
These exist so a purchase chosen on the pricing page can resume inside the app after sign-in. They are stripped from the URL the moment they are read, which means a refresh or a bookmark cannot re-fire a purchase. Treat them as something the pricing page writes, not something to hand-craft.
Parameters written by a return, not by you
Two more arrive on the way back from checkout and are consumed immediately:
status carries the outcome, and prowelcome triggers the post-purchase
message. Setting them by hand shows you the message without the purchase, which is not useful
beyond a test.
The connect flow
/connect handles the OAuth hand-off for
the MCP server and reads code, state and
app, where app is the display name of the client asking. These are part of
the protocol exchange and are not user-facing.
The app also reads a handful of internal flags for development surfaces and modal testing. They are deliberately not documented here: they gate unfinished UI, they change without notice, and one of them exists to let the owner preview a paid surface. Nothing in the public feature set depends on them.
What a parameter cannot do
- Load your file. There is no URL that opens a local path, by design. The tool has no upload endpoint to point at.
- Set an export. Format and scale are chosen at export time, not in a link.
- Grant a tier. A link that applies a Pro look on a free account shows the lock.
Why they are read in the browser
Every parameter on this page is handled client-side after the app mounts, not by a server rewrite. Two consequences worth knowing if you are building links programmatically:
- They work on any deploy, including a preview URL or a local build, because nothing depends on server configuration.
- They are applied after the first paint, so the editor briefly shows its default state before your recipe lands. That is not a bug, and it is why a link always has something on the canvas rather than flashing empty.
Encoding a payload yourself
The r value is the same base64 payload a recipe carries, with the
recipe:v1: prefix removed and padding stripped:
printf '%s' '{"v":1,"renderMode":"dither","ditherPalette":"gameboy"}' \
| base64 | tr -d '=' | tr '+/' '-_'Append the result to /app?r=. The recipe format
covers the payload itself, including what a recipe does and does not carry.
Last updated