From 05bea16782cae9a14b24570c68a1929f3c2bea25 Mon Sep 17 00:00:00 2001 From: Raymond Khalife Date: Wed, 20 May 2026 17:01:55 -0400 Subject: [PATCH] feat(hello-world): Simplify react project and allow frontends with vite preview --- hello-world/react-frontend/app/package.json | 31 --------- .../react-frontend/app/tsconfig.node.json | 4 -- hello-world/react-frontend/app/vite.config.ts | 34 --------- hello-world/react-frontend/canister.yaml | 2 +- .../react-frontend/{app => }/eslint.config.js | 0 .../react-frontend/{app => }/index.html | 0 hello-world/react-frontend/package.json | 33 +++++++-- .../react-frontend/{app => }/public/icp.svg | 0 .../react-frontend/{app => }/public/react.svg | 0 .../react-frontend/{app => }/public/vite.svg | 0 .../react-frontend/{app => }/src/App.css | 0 .../react-frontend/{app => }/src/App.tsx | 0 .../react-frontend/{app => }/src/index.css | 0 .../react-frontend/{app => }/src/main.tsx | 0 .../{app => }/src/vite-env.d.ts | 0 .../{app => }/tsconfig.app.json | 0 .../react-frontend/{app => }/tsconfig.json | 0 hello-world/react-frontend/tsconfig.node.json | 3 +- hello-world/react-frontend/vite.config.ts | 69 +++++++++++++++++++ hello-world/vue-frontend/package.json | 3 +- hello-world/vue-frontend/vite.config.js | 33 --------- hello-world/vue-frontend/vite.config.ts | 69 +++++++++++++++++++ 22 files changed, 171 insertions(+), 110 deletions(-) delete mode 100644 hello-world/react-frontend/app/package.json delete mode 100644 hello-world/react-frontend/app/tsconfig.node.json delete mode 100644 hello-world/react-frontend/app/vite.config.ts rename hello-world/react-frontend/{app => }/eslint.config.js (100%) rename hello-world/react-frontend/{app => }/index.html (100%) rename hello-world/react-frontend/{app => }/public/icp.svg (100%) rename hello-world/react-frontend/{app => }/public/react.svg (100%) rename hello-world/react-frontend/{app => }/public/vite.svg (100%) rename hello-world/react-frontend/{app => }/src/App.css (100%) rename hello-world/react-frontend/{app => }/src/App.tsx (100%) rename hello-world/react-frontend/{app => }/src/index.css (100%) rename hello-world/react-frontend/{app => }/src/main.tsx (100%) rename hello-world/react-frontend/{app => }/src/vite-env.d.ts (100%) rename hello-world/react-frontend/{app => }/tsconfig.app.json (100%) rename hello-world/react-frontend/{app => }/tsconfig.json (100%) create mode 100644 hello-world/react-frontend/vite.config.ts delete mode 100644 hello-world/vue-frontend/vite.config.js create mode 100644 hello-world/vue-frontend/vite.config.ts diff --git a/hello-world/react-frontend/app/package.json b/hello-world/react-frontend/app/package.json deleted file mode 100644 index 15d633d..0000000 --- a/hello-world/react-frontend/app/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "app", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@icp-sdk/core": "~5.2.0", - "react": "~19.1.1", - "react-dom": "~19.1.1" - }, - "devDependencies": { - "@eslint/js": "~9.33.0", - "@icp-sdk/bindgen": "^0.4.0", - "@types/react": "~19.1.10", - "@types/react-dom": "~19.1.7", - "@vitejs/plugin-react": "~5.0.0", - "eslint": "~9.33.0", - "eslint-plugin-react-hooks": "~5.2.0", - "eslint-plugin-react-refresh": "~0.4.20", - "globals": "~16.3.0", - "typescript": "~5.8.3", - "typescript-eslint": "~8.39.1", - "vite": "~7.1.11" - } -} diff --git a/hello-world/react-frontend/app/tsconfig.node.json b/hello-world/react-frontend/app/tsconfig.node.json deleted file mode 100644 index 3cbd3a5..0000000 --- a/hello-world/react-frontend/app/tsconfig.node.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../tsconfig.node.json", - "include": ["vite.config.ts"] -} \ No newline at end of file diff --git a/hello-world/react-frontend/app/vite.config.ts b/hello-world/react-frontend/app/vite.config.ts deleted file mode 100644 index 5797736..0000000 --- a/hello-world/react-frontend/app/vite.config.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import { icpBindgen } from "@icp-sdk/bindgen/plugins/vite"; - -// Change these values to match your local replica. -// The `icp network start` command will print the root key -// and the `icp deploy` command will print the backend canister id. -const IC_ROOT_KEY_HEX = - "308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008b52b4994f94c7ce4be1c1542d7c81dc79fea17d49efe8fa42e8566373581d4b969c4a59e96a0ef51b711fe5027ec01601182519d0a788f4bfe388e593b97cd1d7e44904de79422430bca686ac8c21305b3397b5ba4d7037d17877312fb7ee34"; -const BACKEND_CANISTER_ID = "txyno-ch777-77776-aaaaq-cai"; - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [ - react(), - icpBindgen({ - didFile: "../../backend/backend.did", - outDir: "./src/backend/api", - }), - ], - server: { - headers: { - "Set-Cookie": `ic_env=${encodeURIComponent( - `ic_root_key=${IC_ROOT_KEY_HEX}&PUBLIC_CANISTER_ID:backend=${BACKEND_CANISTER_ID}` - )}; SameSite=Lax;`, - }, - proxy: { - "/api": { - target: "http://127.0.0.1:8000", - changeOrigin: true, - }, - }, - }, -}); diff --git a/hello-world/react-frontend/canister.yaml b/hello-world/react-frontend/canister.yaml index 3a684e6..a9273aa 100644 --- a/hello-world/react-frontend/canister.yaml +++ b/hello-world/react-frontend/canister.yaml @@ -11,4 +11,4 @@ recipe: # Eventually you might want to use `npm ci` to lock your dependencies - npm install - npm run build - dir: app/dist + dir: dist diff --git a/hello-world/react-frontend/app/eslint.config.js b/hello-world/react-frontend/eslint.config.js similarity index 100% rename from hello-world/react-frontend/app/eslint.config.js rename to hello-world/react-frontend/eslint.config.js diff --git a/hello-world/react-frontend/app/index.html b/hello-world/react-frontend/index.html similarity index 100% rename from hello-world/react-frontend/app/index.html rename to hello-world/react-frontend/index.html diff --git a/hello-world/react-frontend/package.json b/hello-world/react-frontend/package.json index 657334f..a0c9a50 100644 --- a/hello-world/react-frontend/package.json +++ b/hello-world/react-frontend/package.json @@ -1,9 +1,32 @@ { - "name": "icp-frontend-environment-variables", + "name": "app", + "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "build": "npm run build --workspaces" + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" }, - "workspaces": [ - "app" - ] + "dependencies": { + "@icp-sdk/core": "~5.2.0", + "react": "~19.1.1", + "react-dom": "~19.1.1" + }, + "devDependencies": { + "@eslint/js": "~9.33.0", + "@icp-sdk/bindgen": "^0.4.0", + "@types/node": "^25.9.1", + "@types/react": "~19.1.10", + "@types/react-dom": "~19.1.7", + "@vitejs/plugin-react": "~5.0.0", + "eslint": "~9.33.0", + "eslint-plugin-react-hooks": "~5.2.0", + "eslint-plugin-react-refresh": "~0.4.20", + "globals": "~16.3.0", + "typescript": "~5.8.3", + "typescript-eslint": "~8.39.1", + "vite": "~7.1.11" + } } diff --git a/hello-world/react-frontend/app/public/icp.svg b/hello-world/react-frontend/public/icp.svg similarity index 100% rename from hello-world/react-frontend/app/public/icp.svg rename to hello-world/react-frontend/public/icp.svg diff --git a/hello-world/react-frontend/app/public/react.svg b/hello-world/react-frontend/public/react.svg similarity index 100% rename from hello-world/react-frontend/app/public/react.svg rename to hello-world/react-frontend/public/react.svg diff --git a/hello-world/react-frontend/app/public/vite.svg b/hello-world/react-frontend/public/vite.svg similarity index 100% rename from hello-world/react-frontend/app/public/vite.svg rename to hello-world/react-frontend/public/vite.svg diff --git a/hello-world/react-frontend/app/src/App.css b/hello-world/react-frontend/src/App.css similarity index 100% rename from hello-world/react-frontend/app/src/App.css rename to hello-world/react-frontend/src/App.css diff --git a/hello-world/react-frontend/app/src/App.tsx b/hello-world/react-frontend/src/App.tsx similarity index 100% rename from hello-world/react-frontend/app/src/App.tsx rename to hello-world/react-frontend/src/App.tsx diff --git a/hello-world/react-frontend/app/src/index.css b/hello-world/react-frontend/src/index.css similarity index 100% rename from hello-world/react-frontend/app/src/index.css rename to hello-world/react-frontend/src/index.css diff --git a/hello-world/react-frontend/app/src/main.tsx b/hello-world/react-frontend/src/main.tsx similarity index 100% rename from hello-world/react-frontend/app/src/main.tsx rename to hello-world/react-frontend/src/main.tsx diff --git a/hello-world/react-frontend/app/src/vite-env.d.ts b/hello-world/react-frontend/src/vite-env.d.ts similarity index 100% rename from hello-world/react-frontend/app/src/vite-env.d.ts rename to hello-world/react-frontend/src/vite-env.d.ts diff --git a/hello-world/react-frontend/app/tsconfig.app.json b/hello-world/react-frontend/tsconfig.app.json similarity index 100% rename from hello-world/react-frontend/app/tsconfig.app.json rename to hello-world/react-frontend/tsconfig.app.json diff --git a/hello-world/react-frontend/app/tsconfig.json b/hello-world/react-frontend/tsconfig.json similarity index 100% rename from hello-world/react-frontend/app/tsconfig.json rename to hello-world/react-frontend/tsconfig.json diff --git a/hello-world/react-frontend/tsconfig.node.json b/hello-world/react-frontend/tsconfig.node.json index 716d8b9..f85a399 100644 --- a/hello-world/react-frontend/tsconfig.node.json +++ b/hello-world/react-frontend/tsconfig.node.json @@ -20,5 +20,6 @@ "erasableSyntaxOnly": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true - } + }, + "include": ["vite.config.ts"] } diff --git a/hello-world/react-frontend/vite.config.ts b/hello-world/react-frontend/vite.config.ts new file mode 100644 index 0000000..405d3f0 --- /dev/null +++ b/hello-world/react-frontend/vite.config.ts @@ -0,0 +1,69 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { icpBindgen } from "@icp-sdk/bindgen/plugins/vite"; +import { execSync } from "child_process"; + + +export default defineConfig(({ command }) => { + const plugins = [ + react(), + icpBindgen({ + didFile: "../backend/backend.did", + outDir: "./src/backend/api", + }), + ]; + + // If we're only building this is enough + if (command !== "serve") { + return { plugins }; + } + + // If we're running the local local npm server, we're going + // to lookup the local network's root key and the relevant + // canister ids + const environment = process.env.ICP_ENVIRONMENT || "local"; + const CANISTER_NAME = "backend"; + + const networkStatus = JSON.parse( + execSync(`icp network status -e ${environment} --json`, { encoding: "utf-8" }) + ); + const rootKey: string = networkStatus.root_key; + const proxyTarget: string = networkStatus.api_url; + + // Backend must be deployed before starting dev server + let canisterId: string; + try { + canisterId = execSync(`icp canister status ${CANISTER_NAME} -e ${environment} -i`, { + encoding: "utf-8", + }).trim(); + } catch { + console.error(` + Backend canister "${CANISTER_NAME}" not found in environment "${environment}" + + Before running the dev server, deploy the backend canister: + + icp deploy ${CANISTER_NAME} -e ${environment} + `); + process.exit(1); + } + + const server = { + headers: { + "Set-Cookie": `ic_env=${encodeURIComponent( + `PUBLIC_CANISTER_ID:${CANISTER_NAME}=${canisterId}&ic_root_key=${rootKey}` + )}; SameSite=Lax;`, + }, + proxy: { + "/api": { + target: proxyTarget, + changeOrigin: true, + }, + }, + }; + + return { + plugins, + server + }; + +}); diff --git a/hello-world/vue-frontend/package.json b/hello-world/vue-frontend/package.json index 8821e46..b6bf096 100644 --- a/hello-world/vue-frontend/package.json +++ b/hello-world/vue-frontend/package.json @@ -1,5 +1,5 @@ { - "name": "MotokoVue_frontend", + "name": "frontend", "version": "0.0.0", "scripts": { "build": "vite build", @@ -13,6 +13,7 @@ }, "devDependencies": { "@icp-sdk/bindgen": "^0.4.0", + "@types/node": "^25.9.1", "@vitejs/plugin-vue": "~6.0.7", "@vue/tsconfig": "^0.9.1", "sass-embedded": "^1.99.0", diff --git a/hello-world/vue-frontend/vite.config.js b/hello-world/vue-frontend/vite.config.js deleted file mode 100644 index f766382..0000000 --- a/hello-world/vue-frontend/vite.config.js +++ /dev/null @@ -1,33 +0,0 @@ -import { defineConfig } from 'vite'; -import vue from '@vitejs/plugin-vue'; -import { icpBindgen } from '@icp-sdk/bindgen/plugins/vite'; - -// Change these values to match your local replica. -// The `icp network start` command will print the root key -// and the `icp deploy` command will print the backend canister id. -const IC_ROOT_KEY_HEX = - "308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361008b52b4994f94c7ce4be1c1542d7c81dc79fea17d49efe8fa42e8566373581d4b969c4a59e96a0ef51b711fe5027ec01601182519d0a788f4bfe388e593b97cd1d7e44904de79422430bca686ac8c21305b3397b5ba4d7037d17877312fb7ee34"; -const BACKEND_CANISTER_ID = "txyno-ch777-77776-aaaaq-cai"; - -export default defineConfig({ - plugins: [ - vue(), - icpBindgen({ - didFile: '../backend/backend.did', - outDir: './src/bindings' - }), - ], - server: { - headers: { - "Set-Cookie": `ic_env=${encodeURIComponent( - `ic_root_key=${IC_ROOT_KEY_HEX}&PUBLIC_CANISTER_ID:backend=${BACKEND_CANISTER_ID}` - )}; SameSite=Lax;`, - }, - proxy: { - '/api': { - target: 'http://127.0.0.1:8000', - changeOrigin: true, - }, - }, - }, -}); diff --git a/hello-world/vue-frontend/vite.config.ts b/hello-world/vue-frontend/vite.config.ts new file mode 100644 index 0000000..e384bb9 --- /dev/null +++ b/hello-world/vue-frontend/vite.config.ts @@ -0,0 +1,69 @@ +import { defineConfig } from "vite"; +import vue from '@vitejs/plugin-vue'; +import { icpBindgen } from "@icp-sdk/bindgen/plugins/vite"; +import { execSync } from "child_process"; + + +export default defineConfig(({ command }) => { + const plugins = [ + vue(), + icpBindgen({ + didFile: '../backend/backend.did', + outDir: './src/bindings' + }), + ]; + + // If we're only building this is enough + if (command !== "serve") { + return { plugins }; + } + + // If we're running the local local npm server, we're going + // to lookup the local network's root key and the relevant + // canister ids + const environment = process.env.ICP_ENVIRONMENT || "local"; + const CANISTER_NAME = "backend"; + + const networkStatus = JSON.parse( + execSync(`icp network status -e ${environment} --json`, { encoding: "utf-8" }) + ); + const rootKey: string = networkStatus.root_key; + const proxyTarget: string = networkStatus.api_url; + + // Backend must be deployed before starting dev server + let canisterId: string; + try { + canisterId = execSync(`icp canister status ${CANISTER_NAME} -e ${environment} -i`, { + encoding: "utf-8", + }).trim(); + } catch { + console.error(` + Backend canister "${CANISTER_NAME}" not found in environment "${environment}" + + Before running the dev server, deploy the backend canister: + + icp deploy ${CANISTER_NAME} -e ${environment} + `); + process.exit(1); + } + + const server = { + headers: { + "Set-Cookie": `ic_env=${encodeURIComponent( + `PUBLIC_CANISTER_ID:${CANISTER_NAME}=${canisterId}&ic_root_key=${rootKey}` + )}; SameSite=Lax;`, + }, + proxy: { + "/api": { + target: proxyTarget, + changeOrigin: true, + }, + }, + }; + + return { + plugins, + server + }; + +});