create-definite-app
v0.1.2
Published
Scaffold a Definite data app from an app.json manifest. Pairs with @definite-app/data-apps.
Maintainers
Readme
create-definite-app
Scaffold a Definite data app from an app.json
manifest. Pairs with @definite-app/data-apps
(the framework: build script, runtime, components).
Usage
# Blank scaffold (refined-shell template)
npx create-definite-app my-app
# Manifest-driven: write app.json first, scaffold + generate App.tsx + build
npx create-definite-app my-app --from ./app.json
# Pipe via stdin
cat app.json | npx create-definite-app my-app --from -The CLI:
- Reads the manifest (or starts from a placeholder if
--fromis omitted). - Infers per-column roles (date / measure / id / label / category) from your SQL aliases — no warehouse round-trip required.
- Generates
src/App.tsx: refined sidebar shell, one nav item per resource, KPI strip from numeric measures, time-series chart when a date column is present. - Writes
package.json+src/main.tsx+app.json+.gitignore. - (Optional)
npm installs@definite-app/data-apps, then runs the build. - (Optional) Probes the warehouse via
DESCRIBEto emit typed.d.tsand fail loudly on HUGEINT/UHUGEINT (which silently round-trips to 0 in DuckDB WASM). - (Optional) Headless-renders the build with a mock bridge and fails on any
console.error/ mountedErrorState.
Flags
| Flag | Default | Effect |
|------|---------|--------|
| --from <path\|-> | (blank scaffold) | Source manifest. - reads stdin. |
| --toolkit-dir <path> | (npm install) | Use an existing @definite-app/data-apps install via symlink — pass either the install root (a dir containing node_modules/@definite-app/data-apps) or the package directory itself. The CLI symlinks the entire node_modules/ so React + esbuild + the toolkit all resolve in one shot. Skip npm install. |
| --no-install | off | Don't run npm install. |
| --no-build | off | Don't run the build. |
| --force | off | Overwrite the target directory if it exists. Default behavior is to auto-disambiguate by appending -2, -3, etc. so an existing app is never silently overwritten. |
| --validate <levels> | static | Comma list: none\|static\|schema\|render. schema and render are explicit opt-ins. |
| --api-key <key> | $DEFINITE_API_KEY | Definite API key for --validate=schema (also reads $DEFINITE_API_BASE_URL for the host and $_TABLE_INTEGRATION_ID for the integration). |
| -o, --out <dir> | first positional | Target directory. |
| -v, --version | | Print version. |
| -h, --help | | Show help. |
Output (machine-readable)
The CLI prints these key=value lines on success so a parent agent can parse the resolved slug + drive paths without scraping prose:
RESULT_APP_DIR=/full/path/to/<slug>
RESULT_SLUG=<slug> # may be auto-suffixed
RESULT_DRIVE_FILE=apps-v2/<slug>/dist/index.html
RESULT_DRIVE_FILE_EMBEDDED=apps-v2/<slug>/dist/index.embedded.html<slug> reflects the actual directory used after auto-disambiguation. If you requested posthog-events and apps-v2/posthog-events/ was already populated, RESULT_SLUG will be posthog-events-2 (or -3, etc.) — pass that to your wrapper Doc YAML, not the slug you originally requested.
Manifest shape (v2)
{
"version": 2,
"name": "Revenue Explorer",
"entry": "src/main.tsx",
"resources": {
"txns": {
"kind": "dataset",
"source": {
"type": "sql",
"sql": "SELECT id AS transactionId, STRFTIME(created_at, '%Y-%m-%d') AS transactionDate, amount::DOUBLE AS amount FROM LAKE.SCHEMA.transactions LIMIT 200000"
}
}
}
}The CLI reads SQL aliases (AS transactionDate, amount::DOUBLE AS amount)
to infer column roles. STRFTIME / DATE_TRUNC / *Date|*At aliases →
date. ::DOUBLE|::BIGINT|::INTEGER casts or SUM/AVG/COUNT(...) wraps →
measure. Names like *Id|*Name|*Label → id|label. Everything else →
category.
License
Apache 2.0 — see LICENSE in the parent repo.
