Local init testing
Use this when you change product/create (bootstrap) or product/init and want to exercise the full path locally without pushing to GitHub or cloning saflib again.
Requirements
- Node.js 22+ (product monorepo
engines; Node 26+ if you usesaf-create/run.tsdirectly) - git and npm
- A local saflib checkout (this repo)
Full bootstrap + init (recommended)
product/create/repro-local.sh creates a throwaway product monorepo under $TMPDIR (or /tmp), copies your current saflib checkout into saflib/, and runs the same bootstrap + product/init sequence as saf-create.
# From the saflib repo root
./product/create/repro-local.sh <name> [<domain>]| Argument | Default | Purpose |
|---|---|---|
<name> | testprod | Product name (kebab-case) |
<domain> | <name>.com | Product domain passed to product/init |
The product directory is:
export TEST_DIR="${TMPDIR:-/tmp}/saf-bootstrap-test-<name>"Why /tmp? The repro intentionally lives outside any parent monorepo (for example saf-2025). That avoids npm resolving dependencies from a parent node_modules during install and test. saflib is copied (not symlinked) so CLI scripts resolve modules under the product tree.
Example:
./product/create/repro-local.sh initdoc initdoc.com
cd "${TMPDIR:-/tmp}/saf-bootstrap-test-initdoc"Bootstrap takes about one to two minutes (platform override sync, two npm install passes, lock-prune, and the full product/init workflow).
Verify the result
From the product monorepo root ($TEST_DIR):
1. Tests
npm testExpect 26 test files / 64 tests for a fresh golden product.
If db or http integration tests fail with Could not locate the bindings file for better-sqlite3, rebuild the native module once (bootstrap runs npm install --ignore-scripts before approving native scripts):
npm rebuild better-sqlite3
npm test2. Typecheck
npm run typecheckThis runs root vue-tsc -b across the product and linked saflib workspaces.
3. Client build (optional)
Source the product dev env, then build the Vite client bundle:
set -a
source <name>/dev/env.dev
set +a
npm run build --workspace=<name>/clients/buildReplace <name> with your product name (for example initdoc).
Re-run after changes
repro-local.sh deletes and recreates $TEST_DIR on each run. After editing bootstrap or init logic:
./product/create/repro-local.sh initdoc initdoc.com
cd "${TMPDIR:-/tmp}/saf-bootstrap-test-initdoc"
npm rebuild better-sqlite3 # if db/http tests fail on bindings
npm test
npm run typecheckInit only (existing monorepo)
If the repo already has a saflib/ submodule and root scaffold, run init from the monorepo root:
npm exec saf-workflow kickoff product/init <name> <domain>See product/init for the full checklist. Do not use this when saflib is missing — use saf-create or repro-local.sh instead.
Faster smoke: --productOnly
For a quicker check that copies only the golden product tree (skips deploy, scaffold, and kratos steps):
npm exec saf-workflow kickoff product/init <name> <domain> --productOnlyUse this in disposable directories only; it is intended for CI-style smoke tests, not a complete product setup.
Cleanup
rm -rf "${TMPDIR:-/tmp}/saf-bootstrap-test-<name>"Related docs
- Overview — create vs init
- saf-create / bootstrap — production install path
- product/init — workflow checklist