diff --git a/deploy/nginx-hicad-zoo-ws.conf.template b/deploy/nginx-hicad-zoo-ws.conf.template
index 3106772db..a68500f8d 100644
--- a/deploy/nginx-hicad-zoo-ws.conf.template
+++ b/deploy/nginx-hicad-zoo-ws.conf.template
@@ -17,6 +17,7 @@ location ^~ /vendor/zoo-modeling-app/fonts/ {
location = /vendor/zoo-modeling-app/kcl_wasm_lib_bg.wasm {
root /var/www/ai-chatbot/public;
try_files $uri =404;
+ gzip_static on;
add_header Cache-Control "public, max-age=3600" always;
}
diff --git a/playwright.helpers.config.ts b/playwright.helpers.config.ts
index 1c10d4ef4..f30d2518d 100644
--- a/playwright.helpers.config.ts
+++ b/playwright.helpers.config.ts
@@ -14,6 +14,7 @@ export default defineConfig({
/routes\/canvas-runtime-internal-endpoint\.test\.ts/,
/routes\/model-classification\.test\.ts/,
/routes\/clawd-request-lifecycle\.test\.ts/,
+ /routes\/hicad-embedded-performance\.test\.ts/,
],
fullyParallel: true,
forbidOnly: !!process.env.CI,
diff --git a/scripts/vendor-zoo-modeling-app.mjs b/scripts/vendor-zoo-modeling-app.mjs
index 871816cfe..391df5af4 100644
--- a/scripts/vendor-zoo-modeling-app.mjs
+++ b/scripts/vendor-zoo-modeling-app.mjs
@@ -140,6 +140,12 @@ function patchOfficialSource() {
"
Zoo Design Studio",
" HiCAD"
);
+ replaceSource(
+ "index.html",
+ ' ',
+ `
+ `
+ );
replaceSource(
"src/Router.tsx",
" createBrowserRouter,\n createHashRouter,",
@@ -225,6 +231,19 @@ function patchOfficialSource() {
` className="cursor-pointer"\n id="freeze-frame"`,
` className="absolute inset-0 h-full w-full cursor-pointer"\n id="freeze-frame"`
);
+ replaceSource(
+ "src/components/OpenedProject.tsx",
+ "import { getMlEphantProjectReloadBehavior } from '@src/components/openedProjectUtils'\n",
+ "import { getMlEphantProjectReloadBehavior } from '@src/components/openedProjectUtils'\nimport env from '@src/env'\n"
+ );
+ replaceSource(
+ "src/components/OpenedProject.tsx",
+ ` const needsOnboarded =
+ !window.electron &&`,
+ ` const needsOnboarded =
+ env().VITE_ZOO_API_TOKEN !== '${proxyToken}' &&
+ !window.electron &&`
+ );
replaceSource(
"src/index.tsx",
"import { markOnce } from '@src/lib/performance'\n",
@@ -357,7 +376,7 @@ function ensureWasm() {
function precompressVersionedAssets(assetsDir) {
for (const entry of readdirSync(assetsDir, { withFileTypes: true })) {
- if (!entry.isFile() || !/\.(?:css|js)$/.test(entry.name)) {
+ if (!entry.isFile() || !/\.(?:css|js|wasm)$/.test(entry.name)) {
continue;
}
const assetPath = path.join(assetsDir, entry.name);
@@ -365,6 +384,15 @@ function precompressVersionedAssets(assetsDir) {
}
}
+function precompressRootWasm(buildDir) {
+ const wasmPath = path.join(buildDir, "kcl_wasm_lib_bg.wasm");
+ if (!existsSync(wasmPath)) return;
+ writeFileSync(
+ `${wasmPath}.gz`,
+ gzipSync(readFileSync(wasmPath), { level: 9 })
+ );
+}
+
async function main() {
ensureOfficialSource();
ensureDependencies();
@@ -393,6 +421,7 @@ async function main() {
throw new Error("Zoo Design Studio build did not produce index.html");
}
precompressVersionedAssets(path.join(buildDir, "assets"));
+ precompressRootWasm(buildDir);
cacheBustZooModelingAppAssets(buildDir);
rmSync(outputDir, { force: true, recursive: true });
diff --git a/tests/routes/hicad-embedded-performance.test.ts b/tests/routes/hicad-embedded-performance.test.ts
new file mode 100644
index 000000000..40e936a5f
--- /dev/null
+++ b/tests/routes/hicad-embedded-performance.test.ts
@@ -0,0 +1,43 @@
+import { expect, test } from "@playwright/test";
+import fs from "node:fs";
+import path from "node:path";
+
+const projectRoot = process.cwd();
+
+test.describe("HiCAD embedded startup", () => {
+ test("suppresses the upstream onboarding chooser in embedded mode", () => {
+ const vendorScript = fs.readFileSync(
+ path.join(projectRoot, "scripts/vendor-zoo-modeling-app.mjs"),
+ "utf8"
+ );
+ const localization = fs.readFileSync(
+ path.join(projectRoot, "vendor/zoo-modeling-app/localization.ts"),
+ "utf8"
+ );
+
+ expect(vendorScript).toMatch(
+ /env\(\)\.VITE_ZOO_API_TOKEN !== '\$\{proxyToken\}'/
+ );
+ expect(localization).toContain("[data-testid='onboarding-toast']");
+ });
+
+ test("preloads and serves the CAD wasm using a precompressed asset", () => {
+ const vendorScript = fs.readFileSync(
+ path.join(projectRoot, "scripts/vendor-zoo-modeling-app.mjs"),
+ "utf8"
+ );
+ const nginxTemplate = fs.readFileSync(
+ path.join(projectRoot, "deploy/nginx-hicad-zoo-ws.conf.template"),
+ "utf8"
+ );
+
+ expect(vendorScript).toContain(
+ 'rel="preload" href="./kcl_wasm_lib_bg.wasm"'
+ );
+ expect(vendorScript).toContain("/\\.(?:css|js|wasm)$/");
+ expect(vendorScript).toContain("precompressRootWasm(buildDir)");
+ expect(nginxTemplate).toMatch(
+ /location = \/vendor\/zoo-modeling-app\/kcl_wasm_lib_bg\.wasm \{[\s\S]*?gzip_static on;/
+ );
+ });
+});
diff --git a/vendor/zoo-modeling-app/localization.ts b/vendor/zoo-modeling-app/localization.ts
index 7d8782b22..37f02b274 100644
--- a/vendor/zoo-modeling-app/localization.ts
+++ b/vendor/zoo-modeling-app/localization.ts
@@ -199,6 +199,7 @@ export function installHiCadLocalization() {
}
html[data-hicad-embedded='true'] [data-testid='download-desktop-app'],
html[data-hicad-embedded='true'] [data-testid='billing-remaining-bar'],
+ html[data-hicad-embedded='true'] [data-testid='onboarding-toast'],
html[data-hicad-embedded='true'] [data-hicad-official-account-link] {
display: none !important;
}