Turn a local app into a hosted one
The four things a local app needs before it can be hosted
For when the answer to “It runs on a server for other people, not just on my machine” is yes.
Derived from the Playground's own platform/ layer, which was built by taking a single-owner desktop tool toward hosted mode and finding the gaps the hard way.
Skip the rebuild
You do not write this one. It arrives in your project as ordinary source you can read, change and keep, with its audit record and its caveats beside it.
- Download the Playground. It is free and runs on your own machine.
- Start a new app and tick “It runs on a server for other people, not just on my machine”.
- This block is written in, along with anything else you ticked.
The mistake it removes
The dangerous half of going hosted is not the features you add — it is the assumptions a local app made that stop being true. A local tool can assume one user, one machine, a writable disk and a trusted caller. Hosting breaks all four at once, and the failures are silent: the app keeps serving, just wrongly.
What you still have to do
A copied file cannot own your secrets, your host or your legal obligations. This is the part the block deliberately does not claim.
- The readiness probe deliberately keeps the failure REASON out of the response body. An orchestrator has no session, so that endpoint is public, and 'connect ECONNREFUSED 10.0.0.5:5432' would hand an unauthenticated caller your database's private address.
- This gets an app to SINGLE-tenant hosted. Serving several customers needs per-tenant isolation, which is enterprise-kit's territory and a bigger change than this block.
What lands in your project
node
- node/cloud-kit.js
storeSeam() (local file OR database behind one resolver), readiness() (503 on an unwritable store, reason in the LOG not the body), requireExposureConfig() (refuse to boot half-configured), normalizeRequestPath()/requestPath() (ONE normalization of the request target: protocol-relative '//', repeated and trailing slashes, '.' and '..', percent-encoding decoded before any decision — and a REFUSAL, never a repair, for anything still abnormal), and pathAllowed() (deny is read before allow, both against that same normalized value, and a path on neither list is denied).
sql
- sql/cloud.sql
A minimal docs table for the database side of the seam. Same shape the local JSON store presents, so switching backends changes no calling code.
What you supply
- DATABASE_URL — set it and the seam resolves to the database; unset and it stays a local file
- AUTH_REQUIRED — true means every request needs a session — and the app REFUSES to boot without a passcode set
- AUTH_PASSCODE — minimum length enforced; a guessable passcode on a public port is the same as none
Licensed MIT. It is a starting point, not a finished product.
Get it
Download the Playground See the other blocks
Nothing here is locked. The files are yours, in your folder, under a permissive license.
Questions
- Is Turn a local app into a hosted one audited?
- No. No full audit has been run against this block yet, which is not the same as a pass. What is verified about it is listed on this page, and what is not is listed beside it.
- What do I still have to do myself?
- The readiness probe deliberately keeps the failure REASON out of the response body. An orchestrator has no session, so that endpoint is public, and 'connect ECONNREFUSED 10.0.0.5:5432' would hand an unauthenticated caller your database's private address.
- How do I get this code?
- Download the Playground, start a new app, and tick “It runs on a server for other people, not just on my machine”. The block is written into your project as ordinary source you can read and edit.
All pre-built code blocks · Learn to build from zero · The coding guide