README.md
App Standard — How To
Covers the three things you'll actually do day to day: create a manifest,
test it against reality, and scaffold a new app. See `GOLDEN_RULES.md` for
the structure/rules themselves.
1. Create a manifest
Every app has one authoritative `voice.manifest` at its root.
`project.registry.json` is generated from all manifests — never hand-edit it.
```bash
system/tools/manifest.sh -n invoicing -p websites/apps/invoicing -e api,python -r "billing system"
```
| Flag | Meaning |
|---|---|
| `-n, --name` | app name (required) |
| `-p, --path` | app path (default: `websites/apps/{name}`) |
| `-e, --extensions` | comma-separated declared extensions (`api,python,assets,themes`) |
| `-r, --role` | optional free-text role tag |
| `-v, --skeleton-version` | which standard version this app follows (default `v2`) |
| `-c, --comment` | free-text note |
| `-f, --force` | overwrite an existing manifest (preserves original `date_created`) |
To regenerate `project.registry.json` from every app's manifest:
```bash
system/tools/manifest.sh -g -a websites/apps -s websites/system -o project.registry.json
```
2. Test a manifest against reality
The manifest can list expected files under a `"files"` key. Two tools check
actual disk contents against that list — same behavior, pick whichever fits
your context (CLI vs. web-triggerable):
```bash
system/tools/manifest.diff.sh -n invoicing # both missing + additional (default)
system/tools/manifest.diff.sh -n invoicing -m # missing only
system/tools/manifest.diff.sh -n invoicing -a # additional only
php system/tools/manifest.diff.php -n invoicing -b
```
Exit code `0` = no drift, `2` = drift found (missing and/or additional
files) — safe to use in a pre-deploy check.
Separately, `system/audit/audit.bootstrap.sh` enforces Rule #1 (every entry
point actually includes `paths.php`/`auth.php`, no hardcoded paths/creds):
```bash
system/audit/audit.bootstrap.sh -n invoicing
system/audit/audit.bootstrap.sh --all --apps-root websites/apps --strict # for CI/pre-deploy
```
3. Create a new app from the starter template
`defapp` is the single source of truth for app structure — scaffolding
clones its actual tree rather than keeping a separate folder list, so
changing `defapp` changes what every future app inherits.
```bash
system/tools/scaffold.appname.sh -n invoicing -e api,python -r
```
This:
1. Copies `defapp`'s entire tree to `websites/apps/invoicing/`
2. Renames every `voice` token in filenames to `invoicing`
(`voice.index.php` → `invoicing.index.php`, same for `.env`)
3. Rewrites `voice` tokens inside file contents too
4. Creates any requested extension folders not already in the template
5. Creates the manifest via `manifest.sh` (`-r`/`--registry` flag)
The cloned `voice.index.php` already includes the required
`paths.php`/`auth.php` bootstrap — this is what makes new apps pass
`audit.bootstrap.sh` clean by default, without extra work per app.
After scaffolding, add whatever this app needs to its own `.env`
(`websites/apps/invoicing/.env`) — its own DB credentials, API keys,
whatever's specific to it. `system/.env` only supplies shared defaults;
overriding them per app is normal, not an exception (see `GOLDEN_RULES.md`).
Then verify it's wired up correctly:
```bash
php websites/apps/invoicing/tests/testdb.php
```