From 35ecce5c6978b6277eebb5003948daf67d711ff3 Mon Sep 17 00:00:00 2001 From: David Susskind Date: Tue, 4 Aug 2026 14:50:02 +0300 Subject: [PATCH 1/2] feat(create): scaffold backend-and-client on the vite-plugin client convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The template adopts the same client wiring editor-created apps use: @base44/vite-plugin (supplies the @ alias and the /api dev proxy) + src/lib/app-params.js (the refactored env-only version from apper#18730, byte-identical) + a static base44Client.js on same-origin /api (serverUrl: ''). The app id leaves scaffolded source: it is injected at serve/build time via VITE_BASE44_APP_ID — by base44 dev, dev --remote, build, and deploy --build — instead of being baked in by create. The post-scaffold build in create/scaffold injects it too, and the missing-build-output hint now points at base44 build. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 4 ++ .../cli/commands/project/scaffold-shared.ts | 6 ++- packages/cli/src/core/site/deploy.ts | 10 +++- .../templates/backend-and-client/package.json | 3 +- .../src/api/base44Client.js | 13 ++++++ .../src/api/base44Client.js.ejs | 5 -- .../backend-and-client/src/lib/app-params.js | 28 +++++++++++ .../backend-and-client/vite.config.js | 11 ++--- packages/cli/tests/cli/create.spec.ts | 46 +++++++++++++++++++ 9 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 packages/cli/templates/backend-and-client/src/api/base44Client.js delete mode 100644 packages/cli/templates/backend-and-client/src/api/base44Client.js.ejs create mode 100644 packages/cli/templates/backend-and-client/src/lib/app-params.js diff --git a/CHANGELOG.md b/CHANGELOG.md index f2e18dabd..836bd87c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ - `base44 deploy` (and `base44 site deploy`) can now build first: interactive runs ask, and `--build` / `--no-build` pre-answer the prompt. - `base44 dev --remote` serves the frontend against the production backend: it runs `site.serveCommand` with `VITE_BASE44_APP_ID` and `VITE_BASE44_APP_BASE_URL` pointing at the app's own published URL, without starting the local backend. Fails if the app has no published URL. +### Changed + +- The `backend-and-client` template now scaffolds the same client convention editor-created apps use: `@base44/vite-plugin` + `src/lib/app-params.js`, with the SDK client on same-origin `/api` (`serverUrl: ''`). Under `base44 dev` the plugin proxies `/api` to the local dev backend, so scaffolded apps get local entities and functions; the app id is injected via `VITE_BASE44_APP_ID` by `base44 dev`, `base44 dev --remote`, and the build/deploy commands instead of being baked into source. + ### Fixed - `base44 link` now lists editor-created apps; previously only apps created by the CLI could be linked. diff --git a/packages/cli/src/cli/commands/project/scaffold-shared.ts b/packages/cli/src/cli/commands/project/scaffold-shared.ts index 975bd6b7e..4e1cbf096 100644 --- a/packages/cli/src/cli/commands/project/scaffold-shared.ts +++ b/packages/cli/src/cli/commands/project/scaffold-shared.ts @@ -103,7 +103,11 @@ export async function completeProjectSetup( await execa({ cwd: resolvedPath, shell: true })`${installCommand}`; updateMessage("Building project..."); - await execa({ cwd: resolvedPath, shell: true })`${buildCommand}`; + await execa({ + cwd: resolvedPath, + shell: true, + env: { VITE_BASE44_APP_ID: projectId }, + })`${buildCommand}`; updateMessage("Deploying site..."); return await deploySite(join(resolvedPath, outputDirectory)); diff --git a/packages/cli/src/core/site/deploy.ts b/packages/cli/src/core/site/deploy.ts index cd3123432..5ad52ac98 100644 --- a/packages/cli/src/core/site/deploy.ts +++ b/packages/cli/src/core/site/deploy.ts @@ -16,7 +16,10 @@ export async function deploySite( `Output directory does not exist: ${siteOutputDir}. Make sure to build your project first.`, { hints: [ - { message: "Run your build command (e.g., 'npm run build') first" }, + { + message: + "Run 'base44 build' first (it injects your app id; a bare 'npm run build' does not)", + }, ], }, ); @@ -29,7 +32,10 @@ export async function deploySite( siteOutputDir, { hints: [ - { message: "Run your build command (e.g., 'npm run build') first" }, + { + message: + "Run 'base44 build' first (it injects your app id; a bare 'npm run build' does not)", + }, ], }, ); diff --git a/packages/cli/templates/backend-and-client/package.json b/packages/cli/templates/backend-and-client/package.json index 91b53dfb8..ef34e2bb5 100644 --- a/packages/cli/templates/backend-and-client/package.json +++ b/packages/cli/templates/backend-and-client/package.json @@ -9,7 +9,8 @@ "preview": "vite preview" }, "dependencies": { - "@base44/sdk": "^0.8.3", + "@base44/sdk": "^0.8.40", + "@base44/vite-plugin": "^1.0.30", "lucide-react": "^0.475.0", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/packages/cli/templates/backend-and-client/src/api/base44Client.js b/packages/cli/templates/backend-and-client/src/api/base44Client.js new file mode 100644 index 000000000..5ce25a555 --- /dev/null +++ b/packages/cli/templates/backend-and-client/src/api/base44Client.js @@ -0,0 +1,13 @@ +import { createClient } from '@base44/sdk'; +import { appParams } from '@/lib/app-params'; + +const { appId, token, functionsVersion, appBaseUrl } = appParams; + +export const base44 = createClient({ + appId, + token, + functionsVersion, + serverUrl: '', + requiresAuth: false, + appBaseUrl +}); diff --git a/packages/cli/templates/backend-and-client/src/api/base44Client.js.ejs b/packages/cli/templates/backend-and-client/src/api/base44Client.js.ejs deleted file mode 100644 index c4c0d5967..000000000 --- a/packages/cli/templates/backend-and-client/src/api/base44Client.js.ejs +++ /dev/null @@ -1,5 +0,0 @@ -import { createClient } from '@base44/sdk'; - -export const base44 = createClient({ - appId: '<%= projectId %>', -}); diff --git a/packages/cli/templates/backend-and-client/src/lib/app-params.js b/packages/cli/templates/backend-and-client/src/lib/app-params.js new file mode 100644 index 000000000..6f6424b3f --- /dev/null +++ b/packages/cli/templates/backend-and-client/src/lib/app-params.js @@ -0,0 +1,28 @@ +import { getAccessToken } from '@base44/sdk'; + +const isNode = typeof window === 'undefined'; + +const isClearAccessTokenRequested = () => + !isNode && new URLSearchParams(window.location.search).get("clear_access_token") === 'true'; + +const clearStoredAccessToken = () => { + window.localStorage.removeItem('base44_access_token'); + window.localStorage.removeItem('token'); +} + +const getAppParams = () => { + if (isClearAccessTokenRequested()) { + clearStoredAccessToken(); + } + return { + appId: import.meta.env.VITE_BASE44_APP_ID, + token: getAccessToken(), + functionsVersion: import.meta.env.VITE_BASE44_FUNCTIONS_VERSION, + appBaseUrl: import.meta.env.VITE_BASE44_APP_BASE_URL, + } +} + + +export const appParams = { + ...getAppParams() +} diff --git a/packages/cli/templates/backend-and-client/vite.config.js b/packages/cli/templates/backend-and-client/vite.config.js index 95d423e2d..96cb102c4 100644 --- a/packages/cli/templates/backend-and-client/vite.config.js +++ b/packages/cli/templates/backend-and-client/vite.config.js @@ -1,12 +1,7 @@ -import { defineConfig } from 'vite'; +import base44 from '@base44/vite-plugin'; import react from '@vitejs/plugin-react'; -import path from 'path'; +import { defineConfig } from 'vite'; export default defineConfig({ - plugins: [react()], - resolve: { - alias: { - '@': path.resolve(__dirname, './src'), - }, - }, + plugins: [base44(), react()], }); diff --git a/packages/cli/tests/cli/create.spec.ts b/packages/cli/tests/cli/create.spec.ts index 0da624d8b..0960f8726 100644 --- a/packages/cli/tests/cli/create.spec.ts +++ b/packages/cli/tests/cli/create.spec.ts @@ -76,6 +76,52 @@ describe("create command", () => { expect(config).toContain('"visibility": "public"'); }); + it("scaffolds backend-and-client with the editor-app client convention", async () => { + await t.givenLoggedIn({ email: "test@example.com", name: "Test User" }); + t.api.mockCreateApp({ id: "convention-app-id", name: "Convention App" }); + + const projectPath = join(t.getTempDir(), "convention-app"); + + const result = await t.run( + "create", + "Convention App", + "--path", + projectPath, + "--template", + "backend-and-client", + "--no-skills", + ); + + t.expectResult(result).toSucceed(); + + const client = await readFile( + join(projectPath, "src", "api", "base44Client.js"), + "utf-8", + ); + expect(client).toContain("serverUrl: ''"); + expect(client).toContain("@/lib/app-params"); + expect(client).not.toContain("convention-app-id"); + + const appParams = await readFile( + join(projectPath, "src", "lib", "app-params.js"), + "utf-8", + ); + expect(appParams).toContain("VITE_BASE44_APP_ID"); + expect(appParams).toContain("VITE_BASE44_APP_BASE_URL"); + + const viteConfig = await readFile( + join(projectPath, "vite.config.js"), + "utf-8", + ); + expect(viteConfig).toContain("@base44/vite-plugin"); + + const appConfig = await readFile( + join(projectPath, "base44", ".app.jsonc"), + "utf-8", + ); + expect(appConfig).toContain("convention-app-id"); + }); + it("infers path from name when --path is not provided", async () => { await t.givenLoggedIn({ email: "test@example.com", name: "Test User" }); t.api.mockCreateApp({ id: "inferred-path-id", name: "My App" }); From 620870cddb92a4d1725e5925cd19d24086a37674 Mon Sep 17 00:00:00 2001 From: David Susskind Date: Wed, 5 Aug 2026 10:32:48 +0300 Subject: [PATCH 2/2] fix(create): drop redundant requiresAuth:false from the template client Mirrors apper fbab06de98f (PR #18730) per Netanel's #580 review: the SDK already defaults requiresAuth to false, so the template stops passing it. Co-Authored-By: Claude Fable 5 --- .../cli/templates/backend-and-client/src/api/base44Client.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cli/templates/backend-and-client/src/api/base44Client.js b/packages/cli/templates/backend-and-client/src/api/base44Client.js index 5ce25a555..de614eea5 100644 --- a/packages/cli/templates/backend-and-client/src/api/base44Client.js +++ b/packages/cli/templates/backend-and-client/src/api/base44Client.js @@ -8,6 +8,5 @@ export const base44 = createClient({ token, functionsVersion, serverUrl: '', - requiresAuth: false, appBaseUrl });