Check a site before you publish
check walks a folder and re-runs the validations that run when an agent writes a page, a handler, or a client script. There is no build command. Catch broken front matter, MiniJinja, *.api.sh types, and JS/TS parse errors before the public URL serves them.
Skill source of truth: /skills/check.md.
This is not TypeScript type-checking (typecheck walks for tsconfig.json and reports type errors). check --js only parses *.ts / *.tsx / *.js / *.jsx / *.mjs / *.cjs with SWC (same path as published transpile). It is also not a live HTTP hit (handler-test dry-runs a script against the session workspace).
Done looks like
check --path pages --pages
prints JSON with "ok": true and "errors": []. You then open the existing publish URL. You did not create a second mount to “test.”
Worked example: this guides site
Job: you edited pages/how-to/*.page.md. Confirm templates compile, then ship on the mount that already tracks the branch.
check --path pages --pages
Expected shape (counts change):
{
"ok": true,
"path": "sites/sails-guides/pages",
"files_checked": 33,
"shell_files": 0,
"page_files": 33,
"js_files": 0,
"errors": [],
"warnings": []
}
path is repo-relative. Exit status stays 0 unless the command itself failed (bad path). Read "ok". Warnings still allow "ok": true.
All three kinds, from the site root (pages + shell handlers + JS/TS under the tree):
check --path .
On this guides site that report includes js_files: 1 (public/theme.js) alongside the page count.
--path defaults to the current directory and must stay under $HOME. With no --shell / --pages / --js, all three run. Skips node_modules, .git, target, dist, .sails. Unsupported bash parameter expansions fail closed at compile time (see help doctor).
When "ok" is false
{
"ok": false,
"errors": [
{
"path": "pages/how-to/example.page.md",
"line": 8,
"column": 1,
"kind": "frontmatter",
"message": "…"
}
]
}
kind | Meaning |
|---|---|
frontmatter | YAML on a .page.html / .page.md |
template | MiniJinja failed (same path as publish). line is the source file |
shell | Bash syntax or unknown command in a script |
type | request / respond / tool schema mismatch. line is in the script body after front matter |
javascript | SWC parse failed on a *.ts / *.tsx / *.js / *.jsx / *.mjs / *.cjs file |
Fix the file, run check again, stop when "ok": true. Autosave already updates a published mount.
Worked example: form handler types
Job: you added pages/subscribe.api.sh next to a form. Lint it without POSTing the live URL.
check --path pages --shell
Then prove behavior:
handler-test pages/subscribe.api.sh --method POST --form 'email=ada@example.com'
handler-test prints JSON (kind: api) with status/body. Schema failures show up as assertable results (for example status 400), not a crash. It does not hit the published mount. --auth only accepts {"signed_in":true} or false — you cannot forge sub / role.
See Put a form on a site for a full subscribe form.
Worked example: client JS parse
Job: you edited public/theme.js (or a *.ts / *.tsx under the site). Confirm it parses the same way publish will transpile it.
check --path public --js
Expected shape when the file is clean:
{
"ok": true,
"path": "sites/sails-guides/public",
"files_checked": 1,
"shell_files": 0,
"page_files": 0,
"js_files": 1,
"errors": [],
"warnings": []
}
A syntax error lands in errors with kind: "javascript" and a line / column in that file. Fix the script, re-run until "ok": true.
TypeScript types are a different tool:
typecheck --path site
That walks up for tsconfig.json (or uses platform defaults). It does not compile MiniJinja and it does not replace check --js.
Flags
check help
| Flag | What it does |
|---|---|
| (none) | --shell, --pages, and --js |
--path PATH | Root to walk (default: cwd) |
--shell | *.sh, *.api.sh, *.mcp.sh, *.tool.sh |
--pages | .page.html / .page.md front matter + MiniJinja |
--js | *.ts / *.tsx / *.js / *.jsx / *.mjs / *.cjs SWC parse |
Failure modes
| What you see | What it means | What to do |
|---|---|---|
"ok": false, kind: template | MiniJinja will fail at publish | Fix the component/page; do not guess the live HTML |
"ok": false, kind: frontmatter | YAML / required fields | Match other pages: title, current, draft: false |
"ok": false, kind: type | Handler body vs response: / tool schema | Align respond / tool with the schema; re-run check --shell |
"ok": false, kind: javascript | SWC could not parse the script | Fix syntax at line / column; re-run check --js |
Exit 0 but "ok": false | Normal — validation lives in JSON | Inspect errors; do not treat exit as green |
typecheck clean, pages still break | Different tool | check --pages |
check --js clean, typecheck fails | Parse ≠ types | Fix the reported type errors; keep using both |
You ship create a second name to “test” | Mounts are stable URLs | check, then edit; one mount per folder |
handler-test looks fine, check fails | Dry-run is behavior; check is lint/types/parse | Fix both; ship only when check is "ok": true |
See Publish a site and Static sites.