diff --git a/bun.lock b/bun.lock
index 39695bce..945a1ec2 100644
--- a/bun.lock
+++ b/bun.lock
@@ -105,6 +105,7 @@
"react-map-gl": "8.0.4",
"react-qrcode-logo": "^3.0.0",
"rfc4648": "^1.5.4",
+ "vite": "^7.0.4",
"vite-plugin-html": "^3.2.2",
"zod": "^4.0.5",
"zustand": "5.0.6",
@@ -132,7 +133,6 @@
"tar": "^7.4.3",
"testing-library": "^0.0.2",
"typescript": "^5.8.3",
- "vite": "^7.0.4",
"vitest": "^3.2.4",
},
},
diff --git a/packages/web/index.html b/packages/web/index.html
index a3f799e3..1564f641 100644
--- a/packages/web/index.html
+++ b/packages/web/index.html
@@ -1,6 +1,9 @@
+
+ <%- cookieYesScript %>
+
diff --git a/packages/web/package.json b/packages/web/package.json
index cc603dcd..5c5bc429 100644
--- a/packages/web/package.json
+++ b/packages/web/package.json
@@ -79,6 +79,7 @@
"react-qrcode-logo": "^3.0.0",
"rfc4648": "^1.5.4",
"vite-plugin-html": "^3.2.2",
+ "vite": "^7.0.4",
"zod": "^4.0.5",
"zustand": "5.0.6"
},
@@ -105,7 +106,6 @@
"tar": "^7.4.3",
"testing-library": "^0.0.2",
"typescript": "^5.8.3",
- "vite": "^7.0.4",
"vitest": "^3.2.4"
}
}
diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json
index 2cf253d2..ca292952 100644
--- a/packages/web/tsconfig.json
+++ b/packages/web/tsconfig.json
@@ -22,7 +22,7 @@
"@layouts/*": ["./src/layouts/*"]
}
},
- "include": ["src", "./vite-env.d.ts"],
+ "include": ["src", ".d.ts"],
"exclude": [
"routeTree.gen.ts",
"node_modules",
diff --git a/packages/web/vercel.json b/packages/web/vercel.json
index 6d0ce863..ba67b055 100644
--- a/packages/web/vercel.json
+++ b/packages/web/vercel.json
@@ -10,13 +10,25 @@
{
"source": "/",
"headers": [
+ {
+ "key": "Cross-Origin-Opener-Policy",
+ "value": "same-origin"
+ },
{
"key": "Cross-Origin-Embedder-Policy",
- "value": "require-corp"
+ "value": "credentialless"
},
{
- "key": "Cross-Origin-Opener-Policy",
- "value": "same-origin"
+ "key": "X-Content-Type-Options",
+ "value": "nosniff"
+ },
+ {
+ "key": "Strict-Transport-Security",
+ "value": "max-age=63072000; includeSubDomains; preload"
+ },
+ {
+ "key": "Referrer-Policy",
+ "value": "strict-origin-when-cross-origin"
}
]
}
diff --git a/packages/web/vite-env.d.ts b/packages/web/vite-env.d.ts
index 59e405fe..227e23be 100644
--- a/packages/web/vite-env.d.ts
+++ b/packages/web/vite-env.d.ts
@@ -1,10 +1,12 @@
///
+interface ViteTypeOptions {
+ strictImportMetaEnv: unknown;
+}
+
interface ImportMetaEnv {
- readonly env: {
- readonly VITE_COMMIT_HASH: string;
- readonly VITE_VERSION: string;
- };
+ readonly VITE_COMMIT_HASH: string;
+ readonly VITE_VERSION: string;
}
interface ImportMeta {
diff --git a/packages/web/vite.config.ts b/packages/web/vite.config.ts
index 9c3e0c00..90447309 100644
--- a/packages/web/vite.config.ts
+++ b/packages/web/vite.config.ts
@@ -3,7 +3,7 @@ import path from "node:path";
import process from "node:process";
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
-import { defineConfig } from "vite";
+import { defineConfig, loadEnv } from "vite";
import { createHtmlPlugin } from "vite-plugin-html";
let hash = "";
@@ -24,60 +24,69 @@ try {
}
const CONTENT_SECURITY_POLICY =
- "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' data: https://rsms.me https://cdn.jsdelivr.net; img-src 'self' data:; font-src 'self' data: https://rsms.me https://cdn.jsdelivr.net; worker-src 'self' blob:; object-src 'none'; base-uri 'self';";
+ "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdn-cookieyes.com; style-src 'self' 'unsafe-inline' data: https://rsms.me https://cdn.jsdelivr.net; img-src 'self' data:; font-src 'self' data: https://rsms.me https://cdn.jsdelivr.net; worker-src 'self' blob:; object-src 'none'; base-uri 'self';";
-export default defineConfig({
- plugins: [
- react(),
- tailwindcss(),
- // adding CookieYes script if VITE_COOKIEYES_CLIENT_ID is set (it only runs while in Vercel) for GDPR/CCPA compliance
- createHtmlPlugin({
- inject: {
- data: {
- cookieScript: process.env.VITE_COOKIEYES_CLIENT_ID
- ? ``
- : "",
+export default defineConfig(({ mode }) => {
+ const env = loadEnv(mode, process.cwd());
+
+ return {
+ plugins: [
+ react(),
+ tailwindcss(),
+ // This is for GDPR/CCPA compliance
+ createHtmlPlugin({
+ inject: {
+ data: {
+ cookieYesScript:
+ mode === "production" && env.VITE_COOKIEYES_CLIENT_ID
+ ? ``
+ : "",
+ },
},
+ }),
+ // VitePWA({
+ // registerType: "autoUpdate",
+ // strategies: "generateSW",
+ // devOptions: {
+ // enabled: true,
+ // },
+ // workbox: {
+ // cleanupOutdatedCaches: true,
+ // sourcemap: true,
+ // },
+ // }),
+ ],
+ optimizeDeps: {
+ include: ["react/jsx-runtime"],
+ },
+ define: {
+ "import.meta.env.VITE_COMMIT_HASH": JSON.stringify(hash),
+ "import.meta.env.VITE_VERSION": JSON.stringify(version),
+ },
+ build: {
+ emptyOutDir: true,
+ assetsDir: "./",
+ },
+ resolve: {
+ alias: {
+ "@app": path.resolve(process.cwd(), "./src"),
+ "@pages": path.resolve(process.cwd(), "./src/pages"),
+ "@components": path.resolve(process.cwd(), "./src/components"),
+ "@core": path.resolve(process.cwd(), "./src/core"),
+ "@layouts": path.resolve(process.cwd(), "./src/layouts"),
},
- }),
- // VitePWA({
- // registerType: "autoUpdate",
- // strategies: "generateSW",
- // devOptions: {
- // enabled: true,
- // },
- // workbox: {
- // cleanupOutdatedCaches: true,
- // sourcemap: true,
- // },
- // }),
- ],
- optimizeDeps: {
- include: ["react/jsx-runtime"],
- },
- define: {
- "import.meta.env.VITE_COMMIT_HASH": JSON.stringify(hash),
- "import.meta.env.VITE_VERSION": JSON.stringify(version),
- },
- build: {
- emptyOutDir: true,
- assetsDir: "./",
- },
- resolve: {
- alias: {
- "@app": path.resolve(process.cwd(), "./src"),
- "@pages": path.resolve(process.cwd(), "./src/pages"),
- "@components": path.resolve(process.cwd(), "./src/components"),
- "@core": path.resolve(process.cwd(), "./src/core"),
- "@layouts": path.resolve(process.cwd(), "./src/layouts"),
},
- },
- server: {
- port: 3000,
- headers: {
- "content-security-policy": CONTENT_SECURITY_POLICY,
- "Cross-Origin-Opener-Policy": "same-origin",
- "Cross-Origin-Embedder-Policy": "require-corp",
+ server: {
+ port: 3000,
+ headers: {
+ "content-security-policy": CONTENT_SECURITY_POLICY,
+ "Cross-Origin-Opener-Policy": "same-origin",
+ "Cross-Origin-Embedder-Policy": "credentialless",
+ "X-Content-Type-Options": "nosniff",
+ "Strict-Transport-Security":
+ "max-age=63072000; includeSubDomains; preload",
+ "Referrer-Policy": "strict-origin-when-cross-origin",
+ },
},
- },
+ };
});