Publishing, step by step
Every step from a folder on your computer to a link your coworkers can open. If you just want the short version, it is in getting started.
Before you start
- Node 20.19 or newer.
node --versionsays which you have. A coding agent already needs it, so you probably have it. - An email address you can open. Signing in is a link in your email. There is no password.
- The folder your agent built. Publish the app's own folder, not the root of a repository holding several projects.
You don't need a Spryloom account first: signing in the first time makes one.
Step 1: Choose how you will publish
From your agent (recommended). Add Spryloom to Claude Code, Codex or Cursor once, and then ask. See using Spryloom from your agent for the setup in each one. Steps 2 to 6 still happen, and your agent does them for you.
From a terminal. Install the spry command:
npm install -g spryloom
spry --version
If npm stops with EACCES: permission denied, don't use sudo. Put
npx spryloom wherever you see spry on this page, or see
the troubleshooting page
to install it for good.
Step 2: Sign in, once
From your agent, there is nothing to type: the first time it publishes, it asks for your email address.
From a terminal:
spry login --email you@yourcompany.com
Either way, Spryloom emails you a link and shows you a short code. Open the link, check that the page shows the same code, and confirm. If the codes differ, close the page: someone else started that sign-in, and nothing happens.
Your workspace is decided by your email. If your company's mail runs on Google Workspace, Microsoft 365, Zoho Mail or another business mail service, the first person from your domain to sign in creates the company workspace and everyone after joins it. Any other address, including Gmail and Outlook, gets a personal workspace. Either way, nobody sees your apps until you share them. See security and access.
Step 3: Check the folder
What Spryloom publishes depends on what is in the folder:
| The folder has | It becomes |
|---|---|
One .html or .md file, or index.html and no package.json |
A page. Files, served instantly, no server. |
A page plus lists in spryloom.yaml |
A page that saves data. See data and secrets. |
| A Vite or React project with no server | A page, after Spryloom runs the build. |
package.json with a start script |
An app, with its own server and a Postgres database if it asks for one. |
For an app, four things decide whether it works the first time. Your agent should have done all four:
- It listens on
process.env.PORT, on0.0.0.0. - It reads its database URL and secrets from the environment.
- A lockfile is committed.
- Anything worth keeping goes in the database, not in files next to the code.
To see what Spryloom makes of the folder without publishing anything:
spry check .
Step 4: Say what it is and who it is for
spryloom.yaml in the folder declares the app: what it does, who may open
it, its tables, jobs and email. Your agent writes it. If there isn't one,
spry publish writes it from what it finds, and asks for one sentence it can't
work out:
spry publish . --description "Tracks expenses that need a second look."
Your coworkers read that sentence before opening the app, in the invitation email and on the app's own page.
Who can open it. A new app is private: only you. Before you invite
anybody, change it:
access:
visibility: invited
visibility |
Who can open it |
|---|---|
private |
You and anybody in admins. Nobody can be invited. |
invited |
People you invite by email, and nobody else. |
company |
Anybody at your email domain. Needs a company workspace. |
A single file has no spryloom.yaml, so say it on the command instead:
spry publish q3-report.html --visibility invited
Step 5: Publish
From the app's folder:
spry publish .
Or ask your agent: "publish this for the finance team, only people I invite."
Spryloom shows each stage as it goes:
| Stage | What is happening |
|---|---|
| Preparing | Reading the folder and the manifest. |
| Database | Creating the app's Postgres database, the first time. |
| Building | Installing dependencies and running the build, in its own sandbox. |
| Starting | Starting the new version. |
| Health check | Waiting until the app answers on its port. |
| Jobs | Setting up scheduled jobs, if it has any. |
| Switching over | Sending visitors to the new version. |
A page skips the server stages and is live in seconds. An app usually takes a few minutes.
The work happens on Spryloom, not on your computer. If you close the
terminal or press Ctrl-C, the publish carries on; spry apps shows how it
ended. If it fails, nothing changes: the version that was live stays live.
When it finishes, you get the address:
https://expense-notes.yourcompany-com.spryloom.app
You can also publish a zip or a GitHub repository:
spry publish ./expense-notes.zip
spry publish github.com/you/expense-notes
Step 6: Invite people
spry invite expense-notes --email ryan@yourcompany.com
Or ask your agent to invite them. Each person gets an email saying who invited them and what the app does. They sign in from that email and they are in. They don't need a terminal, an agent or a password. See the coworker guide for what they see.
Inviting someone to a private app is refused, and says so. Change
visibility and publish again first.
Colleagues see only what you share with them. Being in the same company
workspace doesn't show anyone your apps: an app appears in someone's dashboard
only once it is invited for them, or company for everyone at your domain. In
a personal workspace, company isn't available; invite people by name.
Step 7: Keep it running
| To | Run |
|---|---|
| See your apps and whether they are running | spry apps |
| Read what the app printed | spry logs expense-notes |
| Publish a change | spry publish . again. Same address, same data, next version. |
| Go back to the previous version | spry rollback expense-notes |
| Start it again after a crash | spry restart expense-notes |
The dashboard shows the same, plus who has used each app.
Rolling back changes which code runs. It does not undo changes to records, so keep an export of anything you can't afford to lose.
If something goes wrong
Every refusal says what happened and what to do. The common ones:
- npm says
EACCES: usenpx spryloom, neversudo. - The agent has no Spryloom tools: see your agent and Spryloom.
- "The app built, but it isn't accepting requests": it isn't listening on
process.env.PORTand0.0.0.0. - "Build failed: cannot find …": a package is imported but not in
package.json. - A coworker never gets an email: the app is probably still
private.
Everything else is on Troubleshooting.