fix(apply): express static-site build settings so a monorepo app is served, not run (#63) #64

Merged
dan-claude-bot merged 1 commit from fix/static-build-fields into main 2026-07-14 23:49:30 +00:00
dan-claude-bot commented 2026-07-14 23:47:01 +00:00 (Migrated from github.com)

Closes #63.

The bug

apply created applications but dropped install_command, build_command, and is_static — settings the manifest had no field for — so landing (a static Astro site in an npm-workspace monorepo) was built and run from the repo-root package.json, which boots npm run start -w apps/core (the API server), crash-looping on a missing DATABASE_URL.

The change

The build block gains four optional fields Coolify accepts on both the create (POST /applications/private-github-app) and update (PATCH /applications/{uuid}) routes:

build:
  pack: nixpacks
  base_directory: /
  install_command: npm ci
  build_command: npm run build -w apps/landing-site
  publish_directory: /apps/landing-site/dist
  static: true            # -> is_static: serve publish_directory, run no start command
  • apply writes and diffs install_command / build_command / start_command / is_static.
  • draft emits them (they left its NO_HOME list; is_static was never in it — the exact silent loss that caused the crash), and only emits static alongside a publish_directory so a draft always loads.
  • Managing is_static is opt-in. cast emits it only when the manifest declares static: — emitting is_static: false by default would make the first apply PATCH static serving off any un-migrated static/SPA app configured in the UI (and fight a possible pack: static server-side coupling forever). Declare static: true to serve, static: false to guard against a UI flip, or omit it to leave the field alone.
  • Parse-time refusals: static: true with no publish_directory (nothing to serve), and any of the four on a dockercompose app.

Notes

  • The four field names are verified against reference/coolify-openapi-4.1.2.json on both routes.
  • is_static is absent from the vendored OpenAPI response schema, so the read-side boolean coercion (raw.is_static === true || raw.is_static === 1) rests on the Coolify source's boolean cast, not on the vendored file. Flagged for a live confirmation.
  • docs/semantics.md gains a Build settings section.

npm run build / npm test (471 passing) / npm run check all green.

🤖 Generated with Claude Code

Closes #63. ## The bug `apply` created applications but dropped `install_command`, `build_command`, and `is_static` — settings the manifest had no field for — so `landing` (a static Astro site in an npm-workspace monorepo) was built and **run** from the repo-root `package.json`, which boots `npm run start -w apps/core` (the API server), crash-looping on a missing `DATABASE_URL`. ## The change The `build` block gains four optional fields Coolify accepts on both the create (`POST /applications/private-github-app`) and update (`PATCH /applications/{uuid}`) routes: ```yaml build: pack: nixpacks base_directory: / install_command: npm ci build_command: npm run build -w apps/landing-site publish_directory: /apps/landing-site/dist static: true # -> is_static: serve publish_directory, run no start command ``` - `apply` writes and **diffs** `install_command` / `build_command` / `start_command` / `is_static`. - `draft` emits them (they left its `NO_HOME` list; `is_static` was never in it — the exact silent loss that caused the crash), and only emits `static` alongside a `publish_directory` so a draft always loads. - **Managing `is_static` is opt-in.** cast emits it only when the manifest declares `static:` — emitting `is_static: false` by default would make the first apply PATCH static serving **off** any un-migrated static/SPA app configured in the UI (and fight a possible `pack: static` server-side coupling forever). Declare `static: true` to serve, `static: false` to guard against a UI flip, or omit it to leave the field alone. - Parse-time refusals: `static: true` with no `publish_directory` (nothing to serve), and any of the four on a `dockercompose` app. ## Notes - The four field names are verified against `reference/coolify-openapi-4.1.2.json` on both routes. - `is_static` is **absent from the vendored OpenAPI response schema**, so the read-side boolean coercion (`raw.is_static === true || raw.is_static === 1`) rests on the Coolify source's boolean cast, not on the vendored file. Flagged for a live confirmation. - `docs/semantics.md` gains a *Build settings* section. `npm run build` / `npm test` (471 passing) / `npm run check` all green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/cast#64
No description provided.