Skip to content

feat(dev): front the app's dev server with the SDK header contract - #659

Open
netanelgilad wants to merge 1 commit into
mainfrom
claude/inspiring-edison-55ncqj-dev-front-door
Open

netanelgilad wants to merge 1 commit into
mainfrom
claude/inspiring-edison-55ncqj-dev-front-door

Conversation

@netanelgilad

@netanelgilad netanelgilad commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Note

Description

base44 dev now acts as the single front door for the whole app, the way the platform serves it in production: the CLI origin answers /api/apps/** locally (entities, functions, auth, media) and forwards everything else — including the app's own /api routes and the HMR websocket — to the app's dev server. Forwarded requests carry the SDK header contract (Base44-App-Id, Base44-Api-Url, a locally minted service-role Base44-Service-Authorization) after the caller's copies of the platform-owned headers are dropped, so full-stack apps can call createClientFromRequest locally just as they do in production. Previously those headers were absent under base44 dev, so SSR pages and server functions could not build an SDK client at all.

Related Issue

None (internal: base44-dev/apper#25003). Split out of #643, which keeps the deploy-routing changes.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Other (please describe):

Changes Made

  • New createAppServerProxy (src/cli/dev/dev-server/routes/app-server.ts): HTTP proxy + websocket relay into app-owned code. Strips the visitor's Base44-App-Id / Base44-Api-Url / Base44-Service-Authorization / Base44-State / Base44-Functions-Version / X-Base44-App-Url / X-Data-Env before setting the CLI's own, so a caller cannot point the app's SDK (and the credential travelling with it) at a host they chose. Authorization passes through untouched — it is the visitor the app's server code acts as.
  • Routing split in main.ts: PLATFORM_PATH_PATTERN (/api/apps…) stays local; everything else goes to the app dev server. Websocket upgrades follow the same split — REALTIME_PATH (now exported from realtime.ts) keeps the entity-events socket, all other upgrades are relayed.
  • Websockets relayed frame by frame via ws rather than tunnelled: under Bun (the compiled binary), bytes written to a node:http upgrade socket never reach the wire. Client frames sent before the upstream opens are buffered and flushed on open.
  • Loop guard: every forwarded request carries Base44-Dev-Forwarded; seeing it come back answers 508 with the fix (narrow the Vite proxy to /api/apps, or update @base44/vite-plugin) instead of looping.
  • App dev server discovery (serve-runner.ts): ServeRunner reads the first http://localhost:<port> the child announces on startup, stripping ANSI first (Vite bolds the port) and skipping the front door's own port, which the Vite plugin echoes as its proxy target. serve-command-runner.ts threads onOrigin / ignorePort through.
  • dev.ts: wires the origin promise (120s startup timeout with a clear error), passes appServer to createDevServer, and the outro now prints Your app is available at <cli url> instead of telling users to open the frontend dev server's URL.
  • Docs: new docs/dev-server.md topic guide, linked from docs/AGENTS.md; CHANGELOG entry under Changed.
  • Deps: ws + @types/ws added as devDependencies (bundled, per the zero-dependency distribution rule).

Testing

  • I have tested these changes locally
  • I have added/updated tests as needed
  • All tests pass (npm test)

New tests/cli/dev-app-server.spec.ts drives the real dev command against a new with-app-server fixture (a node dev server that announces a Vite-shaped, ANSI-bolded URL and echoes what each request arrived with). Six cases: SDK header injection, dropping the caller's copies, the app's own /api/time route being forwarded, /api/apps staying local, the HMR socket relaying with headers, and the entity-events socket staying local. waitForDevServer in the testkit was updated for the new outro wording. Typecheck, lint and knip are clean locally; the dev specs pass except two pre-existing dev.spec cases that also fail on main in this sandbox (no IPv6) — hence the unchecked box.

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • I have updated docs/ (AGENTS.md) if I made architectural changes

Additional Notes

User-visible workflow change: open the URL base44 dev prints, not the frontend dev server's own URL. Opening the frontend dev server directly still works for pure-frontend apps but bypasses the header contract, so SSR/server-function code will not get an SDK client.


🤖 Generated by Claude | 2026-10-11 12:22 UTC | 5613fbc

`base44 dev` now serves the whole app on one origin. It answers `/api/apps`
itself and forwards everything else, including the app's own `/api` routes
and its HMR websocket, to the app dev server. Forwarded requests carry
`Base44-App-Id`, `Base44-Api-Url` and a service-role credential, and the
caller's copies of those headers are dropped. Full-stack apps can then build
an SDK client with `createClientFromRequest` locally, as they do in
production.

Websockets are relayed at the frame level through `ws`, because the Bun
compiled binary never writes bytes from a node:http upgrade socket to the
wire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tmb4PCrrV2SLRpBjkGAgXJ
@netanelgilad netanelgilad self-assigned this Oct 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/cli@0.1.32-pr.659.5613fbc

Prefer not to change any import paths? Install using npm alias so your code still imports base44:

npm i "base44@npm:@base44-preview/cli@0.1.32-pr.659.5613fbc"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "base44": "npm:@base44-preview/cli@0.1.32-pr.659.5613fbc"
  }
}

Preview published to npm registry — try new features instantly!

netanelgilad pushed a commit that referenced this pull request Oct 11, 2026
The dev-server front door and its tests now live in #659. This branch
keeps only the deploy routing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tmb4PCrrV2SLRpBjkGAgXJ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants