Test and debug
Before you ship, you exercise the app without infrastructure and validate the structure with a tool. Three things make that possible: the mock backend, the simulated auth adapter and fayz doctor.
Mock mode runs everything without a database
A freshly created app is born with "backend": { "provider": "mock" }. That means in-memory sample data — the whole app works without Supabase, without .env, without a network. Every plugin (and every plugin of yours, via createSafeDataProvider) ships a mock provider, so you can develop and demo the full experience before connecting anything. Flipping the switch to real data means changing provider in the manifest — see Supabase.
Simulated auth
In the same spirit, createMockAuthAdapter from @fayz-ai/auth gives you a session signed in as a demo user, persisted in the browser — no login screen, no provider. On the manifest-first path, the auth adapter follows backend.provider: in mock, auth is simulated automatically. That way you can test screens that depend on "being signed in" without setting up real auth. The details are in Auth — overview.
fayz doctor: the safety net
doctor validates the app at rest — without starting anything. Run it after any change:
npx @fayz-ai/cli doctor
It checks three things:
- Manifest structure and architectural boundaries —
manifestVersion, required fields and surface withscaffold. A structural problem makes doctor exit with an error (exit 1). Today doctor validates the shape of the manifest and the boundaries, not the values of enums liketheme.brandorbackend.provider— validation of those values is on the way (there's an SDK fix in PR). - Architecture boundaries — direct provider SDK imports (
provider-import), imports outside the supported surface (off-surface-import), off-surface dependencies. Reported as warnings (soft enforcement — they don't fail the build). - Referenced plugins — every id in the manifest has to resolve to an installed
@fayz-ai/plugin-*factory wired into the generated code, plus locale coverage.
Typical output for a healthy mock app:
⚠ manifest references plugin(s) [dashboard] — each id must resolve to an installed @fayz-ai/plugin-* factory wired in src/plugins.generated.ts or src/config/app.tsx 0 error(s), 1 warning(s)
Read the final summary: N error(s), M warning(s). Errors you fix before moving on; warnings are visibility — the referenced-plugins warning is expected in mock mode (dashboard is resolved by the platform bundle) and isn't a problem. A code-first app (with no app.manifest.json) runs only the boundary checks and passes.
Plan migrations without touching the database
To debug the data layer, db apply --dry-run prints the ordered plan with no network calls and without reading your PAT — always safe to run:
npx @fayz-ai/cli db apply --dry-run
It's how you check what would be applied (and in what order: spine → drizzle → seed → plugins → incubator) before applying for real.
Next: put the app live with Static deploy.