L1: Compile-first
L1 is the second adoption level. You call compileApp() in your build pipeline and produce a CompiledEntrypointBundle that is deterministic, hashed, and CI-verifiable.
Why this exists
Without a compilation step, there is no artifact to inspect, diff in code review, or gate CI on. A raw spec document is a declaration; a compiled artifact is a verifiable guarantee. Every dependency, every entrypoint, and every capability requirement is resolved and committed.
A compiled artifact also tells you exactly what providers your spec needs at deploy time, before deployment begins. Provider mismatches are caught at compile time, not when a user hits an affected code path.
Installation
bun add @gooi/app
# or
npm install @gooi/app
Usage
import { readFileSync } from "node:fs";
import { defineApp } from "@gooi/app/define";
import { compileApp } from "@gooi/app/compile";
const raw = readFileSync("./app.yml", "utf-8");
// defineApp validates the spec and throws with a descriptive error if invalid
const spec = defineApp({ yaml: raw });
// compileApp produces a deterministic, hashed CompiledEntrypointBundle
const bundle = compileApp({ spec });
console.log("App ID:", bundle.appId);
console.log("Artifact hash:", bundle.hash);
console.log("Entrypoints:", Object.keys(bundle.entrypoints));
console.log(
"Capability requirements:",
bundle.capabilityRequirements.map((r) => r.portId)
);
The CompiledEntrypointBundle
The CompiledEntrypointBundle is the canonical output of compilation. It contains:
appId: the application identifier fromapp.idhash: a SHA-256 hash of the deterministically serialized artifactentrypoints: a map of entrypoint IDs to compiled entrypoint descriptorscapabilityRequirements: the full list of capability ports this app needs at runtimesurfaceDispatchPlans: compiled input binding maps for each declared surface
The hash is computed over lexically sorted keys and lexically ordered set-valued fields. Two compilations of the same spec at the same schema version always produce the same hash. Hash mismatches at runtime activation are hard failures.
The compiled artifact is the only thing the runtime executes. The raw spec YAML is never read after compilation. Do not pass the raw spec to createAppRuntime().
Committing compiled artifacts
Committing compiled artifacts to source control gives you diffable history of what changed between deployments. You can gate CI on artifact validity using parseCompiledBundle().
import { parseCompiledBundle } from "@gooi/app/compile";
import { readFileSync } from "node:fs";
const raw = JSON.parse(readFileSync("./dist/bundle.json", "utf-8"));
const result = parseCompiledBundle(raw);
if (!result.success) {
console.error("Bundle is invalid:", result.error.issues);
process.exit(1);
}
What's next
- L2: Embedded Runtime: pass your compiled bundle to
createAppRuntime() - Ecosystem: understand the
capabilityRequirementsthe compiler emits