Open editor →

How share links work

There is no database of shared workflows, because the workflow itself is the link.

Two kinds of link

  • #g= — a workflow link. Opens the editor with the shared graph on the canvas, ready to remix. This is what the 🔗 Share button makes by default.
  • #a= — an app link. Opens the app player with a standalone, ready-to-run app: auto-generated inputs, a Run button, outputs. Beyond the graph it can carry the app's name or its customized HTML/CSS, the creator's language choice, and small sample outputs shown as a preview before the recipient signs in.

In both cases the payload is the serialized graph or app, gzip-compressed and base64url-encoded into the URL fragment — the part after #. (When compression isn't available there are uncompressed fallbacks: #j= for workflows, a u-prefixed #a= for apps.)

Why the fragment matters

Browsers never send the fragment over the network: an HTTP request for https://nanoodle.com/play.html#a=… asks the server for /play.html and nothing more. The #a=… part exists only in your address bar and in the recipient's browser, where the page decodes it locally. Combined with nanoodle being a static site with no analytics, that means the contents of a shared workflow are never observable by nanoodle's hosting — there is nothing server-side that could log, store, or index them.

What a link never contains

  • Your API key. It is not part of the graph and is never serialized into a link or an exported app. Recipients bring their own key.
  • Your uploaded media. Photos, audio and video you dropped into upload nodes (and inpaint sources/masks) are blanked out of share links and exported apps — they stay in your local save only.
  • Your previous results. Generated outputs aren't part of the saved graph format (app links may carry the small preview samples the creator chose to include).

The import side is defensive too: because upload-node media is always a local data: URL when it's legitimate, any remote URL found in those fields of an incoming link is stripped before the graph is applied — so a crafted link can't use a media URL as a tracking beacon that fires when you open it.

Shortening — first-party too

Because the whole workflow rides in the URL, links can get long — too long for some chat apps and social sites. The share dialog has an opt-in ✂ Shorten button using nanolink, nanoodle’s own self-hosted shortener (a tiny Cloudflare Worker + KV with no analytics and no logs) — it handles even very long links.

No third party in the path: a shortener works by storing your full long URL — including the fragment — and bouncing visitors to it. nanolink is nanoodle infrastructure, so no external service ever holds a copy of the link (or the workflow encoded in it); earlier versions used third-party shorteners (da.gd/TinyURL), and those are gone. Nothing is sent anywhere unless you click Shorten — and if the shortener is unreachable, the dialog simply keeps offering the plain long link, which keeps the fragment-never-leaves-the-browser property end to end.

When an app link with inline preview images gets unwieldy, the share flow re-encodes the preview smaller or drops it — and tells you it did — rather than failing silently.

For recipients

Treat shared apps as untrusted, like any web page. Shared apps run sandboxed and never carry the sharer's key; review what an app does before connecting your own key and running it. Nothing runs or spends without your explicit Run.