Live demos: nyc.backspaces.deno.net, voronoi.backspaces.deno.net (Apps, via CLI), and schelling.backspaces.deno.net (Playground, via dashboard) — all deployed below, click to see them running.
Notes on Deno’s hosting platform, as an alternative/companion to the
agentscript.acequia.io WebDAV publishing used for the rest of
Apps/. Written while getting a first app deployed for real — see
Getting a deploy working below for open items.
There are two, unrelated platforms sharing the “Deno Deploy” name:
| Classic | New (current) | |
|---|---|---|
| Dashboard | dash.deno.com |
console.deno.com |
| Model | flat, per-project | org-based |
| Status | shut down (sunset was July 20, 2026) | active |
They do not share data. Classic projects were never auto-migrated, and
dash.deno.com now just redirects to console.deno.com. An old Classic
account/login carries over (email, GitHub link, even a plausible org slug
suggestion), but any old Classic apps are gone unless you still have the
source elsewhere.
Start at docs.deno.com/deploy — the “About Deno Deploy” page links to the dashboard and the rest of the reference docs. Per Deno’s own quickstart, the path is:
console.deno.com and sign in (GitHub or Google) — this creates
your personal Deno account.console.deno.com/orgs/new) — apps
live inside an org, not directly on your personal account, so this step
is required before you can deploy anything.What we actually saw doing this, worth knowing in advance:
console.deno.com redirects straight to
orgs/new until at least one org exists.backspaces, a slug from an old Classic-era account) — that’s just a
suggestion carried over with your login, not evidence anything already
exists under the new system. Any available slug works..../~/billing/verify — Deno states outright
it won’t be charged, and even past the (much higher) verified limits,
apps simply stop serving traffic rather than incurring a bill. Purely
optional for personal-scale use.console.deno.com/account, distinct
from any org’s settings.The dashboard itself is private — visiting console.deno.com/backspaces
while logged out (or in an incognito window) just shows a sign-in screen,
no org/app data leaks. So for anyone without a login, here’s what the org
overview page looks like:

(Org display name was later renamed from the default “Owen Densmore” to match the slug, “Backspaces” — the CLI walkthroughs below still show the old name since they’re transcripts from before that change.)
Since the dashboard is private, viewing a deployed app needs no invite at
all — the live .deno.net URLs are public to anyone with the link. Invites
are only needed for someone who has to log into console.deno.com/backspaces
itself, e.g. to edit the schelling Playground in-browser, run their own
deno deploy CLI commands against this org, or see metrics/logs/billing.
Invite from console.deno.com/backspaces/settings → ”+ Invite User”
→ their GitHub username (email optional, pulled from GitHub if blank).
Caveat: there’s currently no restricted/view-only role — per Deno’s docs, “all members have owner permissions,” so an invite makes someone a full co-owner (can create/delete apps, manage domains, invite/remove other members), not a scoped collaborator. Worth reserving invites for actual collaborators rather than people who just want to look at a demo. The new console is still Early Access, so scoped roles may show up later — nothing indicates it’s in progress as of this writing.
The new console offers three different things under “+ New ___”:
--source local — GitHub is not required. This is the
better fit for the static, no-build HTML/JS folders in this repo.For folders like the ones in Apps/ (self-contained index.html, CDN
imports, no build step), App via CLI is the closest match to what
uploadApps.js already does for WebDAV.
deno deploy CLIBuilt into Deno 2.9+ (auto-downloaded from JSR on first use — no separate install). Run from inside the specific app folder you want to deploy, e.g.:
cd Apps/NYC
deno deploy --org backspaces
Key things learned the hard way:
--org, it can default to your
personal account org instead of prompting — always pass --org <name>
explicitly.deno deploy from a parent folder (e.g.
Apps/ itself) would deploy the entire tree as one app — always cd
into the specific app folder first.pkill -f "deno deploy" from another window.deno.jsonc too.
If you delete an app (e.g. via its Settings page) but leave the folder’s
deno.jsonc pointing at it, the next deno deploy skips the normal
interactive picker and tries to deploy straight to the now-gone app,
failing with The requested app was not found, or you do not have access
to view it. — even deno deploy whoami can fail with a confusing
Already re-attempted authorization error in this state. The persistent
“Unable to interact with keychain” warning on every run is unrelated/
benign (just means auth isn’t cached between invocations) — don’t chase
that when this is the actual cause. Fix: rm deno.jsonc in the app
folder, then re-run.Useful subcommands:
deno deploy whoami # check current auth/org
deno deploy create --org <org> --app <name> \
--source local --runtime-mode static --static-dir . \
--json --non-interactive # scripted/CI-style create
deno deploy --org <org> --app <name> --prod # redeploy over an existing app
For CI/scripted use: set DENO_DEPLOY_TOKEN and pass --json
--non-interactive — emits a single JSON object on stdout, a structured
error envelope on stderr, and stable exit codes (0 OK, 1 GENERIC, 2 USAGE,
3 AUTH, 4 NOT_FOUND, 5 CONFLICT, 6 NETWORK).
Production URL shape: https://{app-slug}.{org-slug}.deno.net.
NYC, step by stepNYC is now live at https://nyc.backspaces.deno.net, deployed via the CLI
from Apps/NYC with no GitHub repo involved. Full interactive sequence, for
next time (each Select ... / bracketed step is an up/down-arrow menu, not
free text — only type where a value is actually shown being entered):
cd Apps/NYC
deno deploy --org backspaces
Select an application: → Create a new application
(not the leftover graceful-blackbird-6334 Playground).app name: → typed nyc (lowercase, hyphens only — same slug rules as
everywhere else in the console).Do you want to deploy from a github repo or locally? → local.Select an app directory: → (root) (no preset) — correct for a bare
index.html with no build step.Do you want to use the detected build configuration? [y/N] → y.
Detected config: no preset, no install/build/pre-deploy commands,
runtime mode static, static directory ., not a single-page app.Create app? [y/N] → y — uploads files and deploys.Result: production URL https://nyc.backspaces.deno.net, a per-revision
preview URL, and a deno.jsonc config file written into Apps/NYC/:
{
"deploy": { "org": "backspaces", "app": "nyc" }
}
That file means future redeploys from Apps/NYC don’t need --org/--app
again — just:
cd Apps/NYC
deno deploy --prod
schelling, a PlaygroundUnlike nyc (an App via CLI), schelling is a Playground — created
through the dashboard, not the CLI, since Playgrounds don’t have a --source
local equivalent. Live at https://schelling.backspaces.deno.net, source
mirrored at ../Schelling/README.md.
Steps that differed from the CLI/App flow:
console.deno.com/backspaces → ”+ New Playground” (the plain
button, not a framework template). This creates an app with a
placeholder name (e.g. eerie-quetzal-5108) and a single starter file,
main.ts, containing a trivial Deno.serve(() => new
Response('Hello, Deno!')).index.html, the pattern is:
index.html, containing the actual page.main.ts with a tiny server that reads and serves it:
const html = await Deno.readTextFile("./index.html")
Deno.serve(() => new Response(html, { headers: { "content-type": "text/html" } }))
{slug}.backspaces.deno.net URL.schelling — same slug-editing UI as the leftover
graceful-blackbird-6334 Playground we found earlier.The source itself (AgentScript’s SchellingModel + GUIDiv controls) came
from src/agentscript/views2gui/schelling.html, with its four imports
changed from local relative paths (/src/Animator.js, etc.) to the
https://agentscript.org/... CDN, since a Playground has no access to
files outside itself.
Voronoi followed the exact same App-via-CLI steps as NYC (also a bare
index.html, no build step) — live at https://voronoi.backspaces.deno.net,
with its own deno.jsonc written into Apps/Voronoi/.
SchellingLive, using TunnelTunnel is different from everything above — it exposes a locally
running server to a public URL, rather than hosting pre-built/static
content. Per Deno’s docs: deno run --tunnel -A main.ts — first run
authenticates via the same browser device-code flow as the CLI, asks which
app to associate the tunnel with, then prints a public URL forwarding to
your local process. Meant for testing webhooks, sharing local dev with
collaborators, or (our case) live demos of something with real server-side
state that a static file can’t provide.
Full writeup and code at ../SchellingLive/README.md
— short version: instead of each visitor running their own independent
client-side copy of the Schelling model (like the schelling Playground
does), one instance runs server-side and broadcasts ticks to every
connected browser over Server-Sent Events, so everyone watches the same
live grid, and anyone’s click (or a shared Restart button) affects it for
everyone at once. Confirmed SchellingModel runs fine headless under plain
deno run — no DOM/browser dependency in the model logic itself, only in
its TwoDraw renderer (which this demo doesn’t use — it draws straight to
a <canvas> from the SSE state instead).
Unlike nyc/voronoi (bare index.html, auto-detected as static),
SchellingLive is a real Deno.serve script — accepting the auto-detected
config here would be wrong (it defaulted to “static,” which would’ve just
served index.html with no backend behind it, breaking every /events,
/toggle, /restart call). At the “Do you want to use the detected build
configuration?” prompt, answer N instead, which walks through manual
config:
server.tsThat deploys it as a real, permanently-running dynamic app — confirmed
live and actually streaming real SSE data at
https://schellinglive.backspaces.deno.net/events, no tunnel required.
Bonus: this means SchellingLive now also works as an always-on shared
demo on its own, independent of Tunnel — Tunnel is still worth showing
separately since it demonstrates a different thing (your own laptop
serving it live), but isn’t strictly required to make this demo work.
switch and --tunnel can’t create apps, only pick existing onesdeno deploy (bare, for creating something new) offers “Create a new
application” in its app-picker. deno deploy switch --org <org> and
deno run --tunnel do not — they only list existing apps. So to tunnel
into a brand-new app, create it first with the normal deno deploy flow
(as above), then run switch/--tunnel and pick it from the list.
Also: deno deploy switch --org <org> writes a deno.jsonc into whatever
folder you happen to run it from, pointing at whichever app you picked —
if you run it from an unrelated folder (we ran it from SchellingLive/
but picked nyc just to complete the org switch), it leaves a wrong
deno.jsonc behind pointing that folder at the wrong app. Delete/fix it
before deploying from that folder for real.
Mid-way through this, deno run --tunnel’s browser auth landed on a
different Deno account than the one used everywhere else — same
display name (“Owen Densmore”), but a different underlying identity
(odensmore@gmail.com via Google, vs. the usual owen@backspaces.net via
GitHub). It had zero access to backspaces, producing confusing errors
one level up (ORGANIZATION_NOT_FOUND, The requested app was not found,
even a JSON-parse crash on whoami).
How to tell: check console.deno.com/account and compare the email
shown, not the name. How it happened isn’t fully clear (likely the browser
auto-selecting a signed-in Google session instead of prompting), but the
fix:
deno deploy logout only clears the CLI’s local token — it does
not sign you out of the browser’s own console.deno.com session.
Both need clearing.redfish at some point) means the browser’s
current org and the CLI’s current org are two independent bits of
state — fixing one doesn’t fix the other. Switch the browser’s org via
the org-switcher dropdown (top-left); switch the CLI’s via
deno deploy switch --org backspaces.deno run --tunnel -A server.ts from SchellingLive/ ran cleanly (no
re-auth needed once the account/org mess above was sorted), connecting to
https://schellinglive--local.backspaces.deno.net — a third URL
pattern, distinct from both the production URL
(schellinglive.backspaces.deno.net) and the per-revision preview pattern
(schellinglive-<revision>.backspaces.deno.net) seen elsewhere. Confirmed
it’s genuinely serving from the local process (live /events data matched
what the running terminal was doing), not the separate permanent
deployment — the two run fully independently, as noted in
../SchellingLive/README.md.
Still open:
deno.jsonc files (and run the deploy) for the
remaining app folders too (Slideshow, ServiceWorkerDemo, CacheDemo,
Blog).deno-deploy.js/.sh sibling to uploadApps.js, looping
deno deploy --org backspaces --app <name> --prod per folder.SchellingLive live to the team (Tunnel is confirmed
working — this is now just about doing the demo itself).