# URL parameters

Source: https://www.ascii-magic.com/docs/deep-links (ASCII Magic documentation)

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 |

> **Note:** 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:

1. **project** Checked first and wins outright. A saved project already contains a recipe and a source, so nothing else needs applying.
2. **r** A shared recipe. Implies a demo source, so the look has something to sit on.
3. **recipe** A named preset, with that preset's own demo source.
4. **demo** Just 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](https://www.ascii-magic.com/docs/mcp) 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.

> **Note:** 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:

`Make a shareable payload`
```bash
printf '%s' '{"v":1,"renderMode":"dither","ditherPalette":"gameboy"}' \
  | base64 | tr -d '=' | tr '+/' '-_'
```

Append the result to `/app?r=`. [The recipe format](https://www.ascii-magic.com/docs/recipes) covers the payload itself, including what a recipe does and does not carry.
