feat(project): default the site block's two build commands - #634
Merged
Merged
Conversation
Contributor
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.1.16-pr.634.619a424Prefer not to change any import paths? Install using npm alias so your code still imports npm i "base44@npm:@base44-preview/cli@0.1.16-pr.634.619a424"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.1.16-pr.634.619a424"
}
}
Preview published to npm registry — try new features instantly! |
A `site` block had to spell out every command, and the platform that runs these projects kept its own copy of the same values to fill the gaps. Defaults live here now, matching what `base44 create` scaffolds: install `npm install`, build `npm run build`, output `./dist`. A block only names what its project does differently. `serveCommand` is deliberately left undefaulted: `base44 dev` reads its absence as "no frontend to run here" and runs the backend alone, and a default would spawn a dev server for every site block — one that fails immediately takes the backend down with it. Commands that exist only to serve a frontend default it themselves. `site` itself stays optional, so "is there a site?" still keys on the block: a backend-only project omits it and has no site. Inside a block the build fields always resolve, which moves two refusals from "this field is missing" to "there is no site block" — `base44 build` and `site deploy` reword their hints, and `deploy` reads the block rather than one field. Projects that declared a partial block change behaviour: they now build and deploy on the defaults instead of being refused. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018G9vtxAUJV6aZ7FYv5cRjL
ronnyrin
force-pushed
the
feat/site-config-defaults
branch
from
September 22, 2026 09:34
6ab4533 to
93d2ceb
Compare
ronnyrin
force-pushed
the
feat/site-config-defaults
branch
from
September 22, 2026 10:10
8a4b166 to
8d9279d
Compare
Review found that defaulting `outputDirectory` turns a field whose absence
means "nothing built to upload" into one that always resolves, and two callers
act on that:
`deployAll` still keyed the upload on the field, so `base44 deploy` on a
`"site": {"serveCommand": ...}` project (the shape of this repo's own
with-serve-command fixture) would resolve `./dist` and either fail a
previously-green deploy after pushing every other resource, or publish whatever
happened to sit in `./dist` — a backend bundle, typically — as the app's site.
`eject`'s guard `installCommand && buildCommand` became dead, so `eject --yes`
would run a network install, a build and a deploy for any ejected app with a
site block, unprompted.
So `outputDirectory` joins `serveCommand` as deliberately undefaulted, which is
the same rule applied consistently: only the two commands whose absence means
nothing default. `hasResourcesToDeploy` needs no change and drops out of the
diff; eject now keys on `outputDirectory` like every other caller. Added the
deploy test that would have caught the first one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018G9vtxAUJV6aZ7FYv5cRjL
ronnyrin
force-pushed
the
feat/site-config-defaults
branch
from
September 22, 2026 10:13
8d9279d to
9c57bb8
Compare
ronnyrin
added a commit
that referenced
this pull request
Sep 22, 2026
Review findings on this PR, plus the merge of #634's outputDirectory change. `--host`/`--port` were composed only onto an `npm run` invocation and otherwise warned and continued with exit 0. For this command's audience — a hosted sandbox — a warning in a stream nobody reads is not a signal: the dev server comes up on whatever address it likes and the CLI reports success. An address that cannot be delivered is now a refusal. `pnpm`, `yarn` and `bun run` join the forwarding shapes, since all three pass trailing arguments to a script and dropping the address for them was the common case. `withServeAddress` returns whether it dropped the address, so the caller cannot mistake "no address to append" for "the address went nowhere" — the difference being a preview that never loads. That removes the second evaluation of the same regex at the call site, and the predicate it needed. The script token was `\S+`, which matches `dev;evil` and `$(id)`: the predicate answered "this forwards arguments" for a line whose second command is what received them. It is a charset now. The composition also used the untrimmed string while the test used the trimmed one. `--port` went through `Number()`, so an empty string became port 0 — a random port, silently — and `0x10`, `1e3` and `5173.0` were all accepted. It is parsed in a Commander argParser now, digits only and in range. `devHostFlag` does not default in the schema, for the same reason `serveCommand` and `outputDirectory` do not: `site dev` is the only reader, and a default permanently erases the difference between a project that wrote `--host` and one that wrote nothing. `site dev` supplies the fallback. Also: knip was failing on an unused exported type, invisible because none of the five code-checking workflows run on a PR that targets another branch. Tests added for the unauthenticated path on both new commands, `--port` rejection, a failing install command and a custom `devHostFlag`; one assertion that could never fail is gone, and the fixture no longer claims the schema defaults `serveCommand`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018G9vtxAUJV6aZ7FYv5cRjL
Both commands default inside a `site` block, so install and build always work there now — the earlier `outputDirectory` check was guarding a config neither writer produces. `ensure_cli_configs` and `eject_service` both emit the full block including `outputDirectory: "./dist"`, and the eject ZIP comes from the latter, so the check could never be the condition that differed. Having a site block is the whole question: a backend-only project has nothing to build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018G9vtxAUJV6aZ7FYv5cRjL
yurynix
approved these changes
Sep 22, 2026
yurynix
left a comment
Contributor
There was a problem hiding this comment.
Best of luck on your quest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Description
Gives the
siteblock's two commands schema-level defaults (installCommand→npm install,buildCommand→npm run build) — the conventionsbase44 createalready scaffolds — so a block only has to name what a project does differently.serveCommandandoutputDirectoryare deliberately left undefaulted: their absence is the signal that there is no frontend to run and nothing built to upload, sobase44 devstill runs the backend alone andbase44 deploystill skips the site step.siteitself stays optional, so "is there a site?" still keys on the block. The practical effect is that a project with a partialsiteblock can now runbase44 buildanddeploy --buildinstead of being refused, and the deploy flow may offer to build first.Related Issue
None
Type of Change
Changes Made
core/project/schema.ts:SiteConfigSchema.buildCommandandinstallCommandchange from.optional()to.default("npm run build")/.default("npm install"), with a comment explaining whyserveCommandandoutputDirectoryare intentionally excluded.cli/commands/project/eject.ts: the post-eject install-build-deploy offer now keys on the presence of asiteblock rather than on both commands being set — that guard went dead once the commands default, and having a block is the whole question, since a backend-only project has nothing to build.cli/commands/project/site-build.ts: the "no build command" hint now tells the user to add asiteblock and notes thatbuildCommanddefaults inside one.docs/deployments.md: thesite deploybuild prompt is now described as firing whenever the project has asiteblock, sincebuildCommanddefaults inside one.CHANGELOG.md: entry under Changed describing the defaults and the deliberate omissions.Testing
npm test)Test changes:
with-site-defaults(empty"site": {}block plus apackage.jsonbuild script that recordsVITE_BASE44_APP_ID).tests/core/project.spec.ts: three cases — a partial block keeps its named field and picks up both command defaults, an empty block defaults both commands while leavingserveCommand/outputDirectoryundefined, and a project with nositeblock still has no site at all.tests/cli/build.spec.ts: the two "fails when the project has no site.buildCommand" cases are replaced by one assertingbuildnow succeeds via the default command; the no-site-block failure case is kept.tests/cli/deploy.spec.ts: guards the deliberate omission — a block with only aserveCommanddeploys no site and never reports "Site from".Checklist
docs/(AGENTS.md) if I made architectural changesAdditional Notes
Behaviour does change for projects that already declared a partial
siteblock: they now build and deploy on the defaults instead of being refused, which is why "Breaking change" is checked alongside "New feature" — no config becomes invalid, but an existing block can do more than it used to.The asymmetry is the point and is worth reviewing on its own terms: defaulting
outputDirectoryto./distwould silently turn anysiteblock into an upload of whatever happened to be sitting there (or fail a previously-green deploy after every other resource had already been pushed), and defaultingserveCommandwould spawn a dev server for every site block. Commands that exist only to serve or build a site supply their own fallback, where the intent is unambiguous.🤖 Generated by Claude | 2026-09-22 10:50 UTC | 619a424