open-form check
Load forms the way the server does and print their schema, or the exact error.
npx open-form check # every form
npx open-form check meetup # one formLoads each form through the same SSR and render-to-collect path the server uses,
without listening on a port, and prints what it derived. It's how your agent
verifies a form before anyone opens it, and it works whether or not
open-form dev is running.
✔ meetup Developer Meetup Registration own theme · v3c9e1a07b2d4
step 1 About you
name text required
email email required
step 2 Background
role select required, 3 options
school text required if role = "Student"
policy max 100 · one per emailWhat it reports
- Schema — each step and its condition, and each field:
name, type,required, the number of options, a custom validator, and its own<When>condition.v…is a fingerprint of the schema; it changes when the fields do. The header line saysown themewhen the form imports itsforms/<id>/theme/, ordefault lookwhen it doesn't. - Policy —
maxResponses,uniqueBy, andopensAt/closesAtwith the time zone they're read in. - Imports — a warning when a form imports from
themes/or from another form's folder. A form's look is written for it in its owntheme/, so changing a theme or another form never changes it. - Unapplied theme — a warning when
forms/<id>/theme/has a look file but the form'sindex.tsxdoesn't import it, so the form shows the default look. - Unused theme components — a warning when the form's own theme defines
components for parts the form never renders: a
Ratingin a form without a rating, or aSelectthat<Form components>replaces. Chrome (Layout,Header,Progress,Nav,Button,Success,Notice,LanguageSwitch,Field) is never flagged. - One response per — a warning when
uniqueBynames a field that isn't there, or one that's optional or conditional: responses that leave it blank or hidden aren't limited. - Time zone — a warning when
opensAt/closesAtare wall-clock dates and neither the form noropen-form.config.tssetstimeZone, since they'd be read in UTC. - Translations — for forms with more than one language,
N/N translatedper language, the missing strings (the first eight here, all of them in--json), and up to three "not seen" entries. - Errors — a form that fails to load prints the exact error.
- Secrets in the config — an error when
open-form.config.tsholds a URL with a password, such as a Postgres connection string instorage.url. The file is committed; read the value fromprocess.envand keep it in.env. The password itself is never printed, andcheckexits with code1.
"Not seen" means a translation key that didn't appear when the form rendered
with no answers. Text shown only for certain answers, or returned by
validate, lands there legitimately; anything else is usually a key left behind
by edited text.
Flags
| Flag | Default | Description |
|---|---|---|
--json | off | Machine-readable output. |
With --json, each form is an object with id, ok, version, theme,
schema, submissions, timeZone, warnings and languages; a form that
failed is { id, ok: false, error }. theme is the project-relative path of the
form's own theme file, such as forms/meetup/theme/index.tsx, or null when
the form has none or doesn't import it.
The command exits with code 1 when any form fails to load, or when there's no
form with the id you gave. Warnings don't change the exit code.
open-form start
Serve the production build from one Node process: form pages, Studio, the submission and admin API, and responses in SQLite on a persistent disk or in Postgres.
open-form create
Create a new form from the starter at forms/<id>/index.tsx, with its own theme/index.ts, optionally starting from a theme's tokens, and print its preview path.