Your app's manifest
spryloom.yaml sits in your app's folder and says what the app is. Spryloom
builds exactly what it declares.
It is a contract, not configuration. It lives in your repository, you can read and edit it by hand, and it is what your coworkers are shown — the description appears in their invitation email, and what the app stores appears on its page. Nothing about your app is inferred behind your back.
Your coding agent writes it while it builds the app. spry init writes one too,
and spry publish writes one if there is none.
The whole thing
app:
name: Expense Notes
slug: expense-notes
description: Tracks expenses that need a second look.
runtime:
frontend: none
backend: node
start: node server.mjs
access:
visibility: company
domain: yourcompany.com
signin: [email_link]
admins: [priya@yourcompany.com]
data:
postgres: true
tables: [expenses, approvals]
uploads: false
jobs:
- name: weekly-digest
command: node jobs/digest.js
schedule: "0 9 * * 1"
timezone: America/New_York
email: true
egress:
- slack.com
jobs, email and egress are optional. Leave them out and the app does
nothing on its own, emails nobody, and reaches nothing outside Spryloom.
app
| Field | |
|---|---|
name |
What people call it. Shown everywhere a person sees the app. |
slug |
The first part of its address, and what commands take. Lower case, letters, digits and hyphens, up to 40 characters. No double hyphen, and it cannot start xn--. Derived from the name if you leave it out. |
description |
One sentence saying what the app does for the person using it. Required. |
The description is the one field worth thinking about. Your coworkers read it before opening something a colleague made, and "internal tool" tells them nothing. Write what it does for them.
name is capped at 60 characters and description at 200. A handful of slugs
are reserved because they would collide with a platform hostname or mislead
somebody reading a URL: www, api, app, admin, docs, status,
support, test and about thirty more. Choosing one is refused, and the
refusal names it.
runtime
| Field | |
|---|---|
frontend |
none, static, or react. |
backend |
none or node. |
start |
The command that starts the app. Required unless you supply a Dockerfile. |
build |
A build command, when the app needs one. Optional. |
dockerfile |
Path to your own Dockerfile. Optional — see below. |
frontend and backend cannot both be none: there would be nothing to run.
Python is named in the plan and is not built. Today this is Node, with a static or React front end.
You do not need a Dockerfile. Spryloom writes one, correctly, from what is here. If your app already has one at its root it is used exactly as it is, and nothing is overwritten. If it lives anywhere else, name it:
runtime:
dockerfile: docker/Dockerfile
The path is relative to the folder you publish, and it has to be inside it. A path that names a file which is not there is refused, rather than ignored in favour of a generated image you did not ask for.
access
| Field | |
|---|---|
visibility |
private, invited, company, or link. |
domain |
Email domain. Required when visibility is company. |
signin |
How people sign in. [email_link] today. |
admins |
Email addresses that get the admin role. Optional. |
See who can use your app for what each of those means and how your app is told which role somebody has.
signin also accepts google, which does nothing yet — do not declare it. The
app's page tells your coworkers how they will actually sign in, and naming a
method that is not there would make that page wrong.
data
| Field | |
|---|---|
postgres |
true gives the app a database of its own. |
tables |
What the app keeps in it. Required when postgres is true, and refused when it is false. |
uploads |
false. true is refused: file uploads are Release 2. |
tables is what you tell people, not what Spryloom creates — your app creates
its own tables. See data and secrets. It is not optional, in
either direction: a database with no tables listed is refused, because your
coworkers read that list on the app's label page before they open it, and so is
a table list on an app with no database.
uploads: true is refused rather than ignored. Declaring something the
platform does not do would put it on the label page, and that page is the one
your coworkers are asked to believe.
jobs
Work the app does on its own, on a schedule. Each run is your app's own code, with its database, its secrets and the same limits as the app, started at the times you give and stopped when the command finishes.
| Field | |
|---|---|
name |
Lower case letters, digits and hyphens. Unique within the app. |
command |
What to run, the way you would type it in the app's folder: node jobs/remind.js. |
schedule |
Five-field cron: minute, hour, day of the month, month, day of the week. "0 9 * * 1-5" is weekdays at 9:00. |
timezone |
The time zone the schedule is read in, such as Europe/London. UTC if you leave it out. |
timeout_minutes |
How long a run may take before it is stopped. 10 if you leave it out, 15 at most. |
During the beta a job runs at most once every 10 hours, an app has at most 5, and a job that fails 5 times in a row is paused and you are emailed. See jobs and email.
email
true lets the app email the people who use it: a short notification with one
button that opens a page in the app. Spryloom sends it and writes the email
around it. At most 5 a day during the beta, and only to people invited to the
app or who have signed in to it. See jobs and email.
egress
The outside services the app may reach, by host name, each from the list at outside APIs. HTTPS only. A host not on that list is refused when you publish, and the refusal says how to ask for it.
Each host is shown on the app's page before anyone signs in, in words: a coworker sees "Reads from and posts to Slack", not just a host name.
Editing it
Change it and publish again. Everything in it takes effect on the next publish: who can use the app, what it is called, what it declares that it stores.
Two things are worth knowing:
- Changing the slug makes a new app, at a new address, with its own database. It does not rename the old one.
- Removing
postgres: truedoes not delete the database. The app stops being given a connection string; the data stays where it is.