diff --git a/apps/admin/.env.example b/apps/admin/.env.example
index 15d7a36a9d..59663aa673 100644
--- a/apps/admin/.env.example
+++ b/apps/admin/.env.example
@@ -1,12 +1,12 @@
-NEXT_PUBLIC_API_BASE_URL="http://localhost:8000"
+VITE_API_BASE_URL="http://localhost:8000"
-NEXT_PUBLIC_WEB_BASE_URL="http://localhost:3000"
+VITE_WEB_BASE_URL="http://localhost:3000"
-NEXT_PUBLIC_ADMIN_BASE_URL="http://localhost:3001"
-NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
+VITE_ADMIN_BASE_URL="http://localhost:3001"
+VITE_ADMIN_BASE_PATH="/god-mode"
-NEXT_PUBLIC_SPACE_BASE_URL="http://localhost:3002"
-NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
+VITE_SPACE_BASE_URL="http://localhost:3002"
+VITE_SPACE_BASE_PATH="/spaces"
-NEXT_PUBLIC_LIVE_BASE_URL="http://localhost:3100"
-NEXT_PUBLIC_LIVE_BASE_PATH="/live"
+VITE_LIVE_BASE_URL="http://localhost:3100"
+VITE_LIVE_BASE_PATH="/live"
diff --git a/apps/admin/Dockerfile.admin b/apps/admin/Dockerfile.admin
index 1cb7a4cb63..05549126c1 100644
--- a/apps/admin/Dockerfile.admin
+++ b/apps/admin/Dockerfile.admin
@@ -28,35 +28,35 @@ FROM base AS installer
ENV NODE_ENV=production
# Public envs required at build time (pick up via process.env)
-ARG NEXT_PUBLIC_API_BASE_URL=""
-ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
-ARG NEXT_PUBLIC_API_BASE_PATH="/api"
-ENV NEXT_PUBLIC_API_BASE_PATH=$NEXT_PUBLIC_API_BASE_PATH
+ARG VITE_API_BASE_URL=""
+ENV VITE_API_BASE_URL=$VITE_API_BASE_URL
+ARG VITE_API_BASE_PATH="/api"
+ENV VITE_API_BASE_PATH=$VITE_API_BASE_PATH
-ARG NEXT_PUBLIC_ADMIN_BASE_URL=""
-ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL
-ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
-ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH
+ARG VITE_ADMIN_BASE_URL=""
+ENV VITE_ADMIN_BASE_URL=$VITE_ADMIN_BASE_URL
+ARG VITE_ADMIN_BASE_PATH="/god-mode"
+ENV VITE_ADMIN_BASE_PATH=$VITE_ADMIN_BASE_PATH
-ARG NEXT_PUBLIC_SPACE_BASE_URL=""
-ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL
-ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
-ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH
+ARG VITE_SPACE_BASE_URL=""
+ENV VITE_SPACE_BASE_URL=$VITE_SPACE_BASE_URL
+ARG VITE_SPACE_BASE_PATH="/spaces"
+ENV VITE_SPACE_BASE_PATH=$VITE_SPACE_BASE_PATH
-ARG NEXT_PUBLIC_LIVE_BASE_URL=""
-ENV NEXT_PUBLIC_LIVE_BASE_URL=$NEXT_PUBLIC_LIVE_BASE_URL
-ARG NEXT_PUBLIC_LIVE_BASE_PATH="/live"
-ENV NEXT_PUBLIC_LIVE_BASE_PATH=$NEXT_PUBLIC_LIVE_BASE_PATH
+ARG VITE_LIVE_BASE_URL=""
+ENV VITE_LIVE_BASE_URL=$VITE_LIVE_BASE_URL
+ARG VITE_LIVE_BASE_PATH="/live"
+ENV VITE_LIVE_BASE_PATH=$VITE_LIVE_BASE_PATH
-ARG NEXT_PUBLIC_WEB_BASE_URL=""
-ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL
-ARG NEXT_PUBLIC_WEB_BASE_PATH=""
-ENV NEXT_PUBLIC_WEB_BASE_PATH=$NEXT_PUBLIC_WEB_BASE_PATH
+ARG VITE_WEB_BASE_URL=""
+ENV VITE_WEB_BASE_URL=$VITE_WEB_BASE_URL
+ARG VITE_WEB_BASE_PATH=""
+ENV VITE_WEB_BASE_PATH=$VITE_WEB_BASE_PATH
-ARG NEXT_PUBLIC_WEBSITE_URL="https://plane.so"
-ENV NEXT_PUBLIC_WEBSITE_URL=$NEXT_PUBLIC_WEBSITE_URL
-ARG NEXT_PUBLIC_SUPPORT_EMAIL="support@plane.so"
-ENV NEXT_PUBLIC_SUPPORT_EMAIL=$NEXT_PUBLIC_SUPPORT_EMAIL
+ARG VITE_WEBSITE_URL="https://plane.so"
+ENV VITE_WEBSITE_URL=$VITE_WEBSITE_URL
+ARG VITE_SUPPORT_EMAIL="support@plane.so"
+ENV VITE_SUPPORT_EMAIL=$VITE_SUPPORT_EMAIL
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
diff --git a/apps/admin/Dockerfile.dev b/apps/admin/Dockerfile.dev
index 0b82669c4b..f5dae8c080 100644
--- a/apps/admin/Dockerfile.dev
+++ b/apps/admin/Dockerfile.dev
@@ -8,7 +8,7 @@ COPY . .
RUN corepack enable pnpm && pnpm add -g turbo
RUN pnpm install
-ENV NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
+ENV VITE_ADMIN_BASE_PATH="/god-mode"
EXPOSE 3000
diff --git a/apps/admin/app/entry.client.tsx b/apps/admin/app/entry.client.tsx
new file mode 100644
index 0000000000..82ea2d9381
--- /dev/null
+++ b/apps/admin/app/entry.client.tsx
@@ -0,0 +1,34 @@
+/* eslint-disable import/order */
+import * as Sentry from "@sentry/react-router";
+import { startTransition, StrictMode } from "react";
+import { hydrateRoot } from "react-dom/client";
+import { HydratedRouter } from "react-router/dom";
+
+Sentry.init({
+ dsn: process.env.VITE_SENTRY_DSN,
+ environment: process.env.VITE_SENTRY_ENVIRONMENT,
+ sendDefaultPii: process.env.VITE_SENTRY_SEND_DEFAULT_PII ? process.env.VITE_SENTRY_SEND_DEFAULT_PII === "1" : false,
+ release: process.env.VITE_APP_VERSION,
+ tracesSampleRate: process.env.VITE_SENTRY_TRACES_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_TRACES_SAMPLE_RATE)
+ : 0.1,
+ profilesSampleRate: process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE)
+ : 0.1,
+ replaysSessionSampleRate: process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE)
+ : 0.1,
+ replaysOnErrorSampleRate: process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE)
+ : 1.0,
+ integrations: [],
+});
+
+startTransition(() => {
+ hydrateRoot(
+ document,
+
+
+
+ );
+});
diff --git a/apps/admin/app/root.tsx b/apps/admin/app/root.tsx
index 657b96094d..89415106d9 100644
--- a/apps/admin/app/root.tsx
+++ b/apps/admin/app/root.tsx
@@ -1,4 +1,5 @@
import type { ReactNode } from "react";
+import * as Sentry from "@sentry/react-router";
import { Links, Meta, Outlet, Scripts } from "react-router";
import type { LinksFunction } from "react-router";
import appleTouchIcon from "@/app/assets/favicon/apple-touch-icon.png?url";
@@ -66,7 +67,11 @@ export function HydrateFallback() {
);
}
-export function ErrorBoundary() {
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+ if (error) {
+ Sentry.captureException(error);
+ }
+
return (
Something went wrong.
diff --git a/apps/admin/package.json b/apps/admin/package.json
index ad4ca6f0bf..959c1ce737 100644
--- a/apps/admin/package.json
+++ b/apps/admin/package.json
@@ -28,11 +28,10 @@
"@plane/ui": "workspace:*",
"@plane/utils": "workspace:*",
"@react-router/node": "^7.9.3",
+ "@sentry/react-router": "catalog:",
"@tanstack/react-virtual": "^3.13.12",
"@tanstack/virtual-core": "^3.13.12",
- "@vercel/edge": "1.2.2",
"axios": "catalog:",
- "dotenv": "^16.4.5",
"isbot": "^5.1.31",
"lodash-es": "catalog:",
"lucide-react": "catalog:",
diff --git a/apps/admin/react-router.config.ts b/apps/admin/react-router.config.ts
index 1f7815ab36..a4cef08832 100644
--- a/apps/admin/react-router.config.ts
+++ b/apps/admin/react-router.config.ts
@@ -1,7 +1,7 @@
import type { Config } from "@react-router/dev/config";
import { joinUrlPath } from "@plane/utils";
-const basePath = joinUrlPath(process.env.NEXT_PUBLIC_ADMIN_BASE_PATH ?? "", "/") ?? "/";
+const basePath = joinUrlPath(process.env.VITE_ADMIN_BASE_PATH ?? "", "/") ?? "/";
export default {
appDirectory: "app",
diff --git a/apps/admin/vite.config.ts b/apps/admin/vite.config.ts
index b343ee347e..8cf2be7f30 100644
--- a/apps/admin/vite.config.ts
+++ b/apps/admin/vite.config.ts
@@ -1,26 +1,23 @@
import path from "node:path";
import { reactRouter } from "@react-router/dev/vite";
-import dotenv from "dotenv";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import { joinUrlPath } from "@plane/utils";
-dotenv.config({ path: path.resolve(__dirname, ".env") });
-
-// Automatically expose all environment variables prefixed with NEXT_PUBLIC_
-const publicEnv = Object.keys(process.env)
- .filter((key) => key.startsWith("NEXT_PUBLIC_"))
- .reduce
>((acc, key) => {
- acc[key] = process.env[key] ?? "";
- return acc;
+// Expose only vars starting with VITE_
+const viteEnv = Object.keys(process.env)
+ .filter((k) => k.startsWith("VITE_"))
+ .reduce>((a, k) => {
+ a[k] = process.env[k] ?? "";
+ return a;
}, {});
-const basePath = joinUrlPath(process.env.NEXT_PUBLIC_ADMIN_BASE_PATH ?? "", "/") ?? "/";
+const basePath = joinUrlPath(process.env.VITE_ADMIN_BASE_PATH ?? "", "/") ?? "/";
export default defineConfig(() => ({
base: basePath,
define: {
- "process.env": JSON.stringify(publicEnv),
+ "process.env": JSON.stringify(viteEnv),
},
build: {
assetsInlineLimit: 0,
diff --git a/apps/space/.env.example b/apps/space/.env.example
index 15d7a36a9d..59663aa673 100644
--- a/apps/space/.env.example
+++ b/apps/space/.env.example
@@ -1,12 +1,12 @@
-NEXT_PUBLIC_API_BASE_URL="http://localhost:8000"
+VITE_API_BASE_URL="http://localhost:8000"
-NEXT_PUBLIC_WEB_BASE_URL="http://localhost:3000"
+VITE_WEB_BASE_URL="http://localhost:3000"
-NEXT_PUBLIC_ADMIN_BASE_URL="http://localhost:3001"
-NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
+VITE_ADMIN_BASE_URL="http://localhost:3001"
+VITE_ADMIN_BASE_PATH="/god-mode"
-NEXT_PUBLIC_SPACE_BASE_URL="http://localhost:3002"
-NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
+VITE_SPACE_BASE_URL="http://localhost:3002"
+VITE_SPACE_BASE_PATH="/spaces"
-NEXT_PUBLIC_LIVE_BASE_URL="http://localhost:3100"
-NEXT_PUBLIC_LIVE_BASE_PATH="/live"
+VITE_LIVE_BASE_URL="http://localhost:3100"
+VITE_LIVE_BASE_PATH="/live"
diff --git a/apps/space/Dockerfile.dev b/apps/space/Dockerfile.dev
index b915aad085..20ac137da8 100644
--- a/apps/space/Dockerfile.dev
+++ b/apps/space/Dockerfile.dev
@@ -12,7 +12,7 @@ RUN pnpm install
EXPOSE 3002
-ENV NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
+ENV VITE_SPACE_BASE_PATH="/spaces"
VOLUME [ "/app/node_modules", "/app/apps/space/node_modules"]
diff --git a/apps/space/Dockerfile.space b/apps/space/Dockerfile.space
index f6787619ec..cb2d925884 100644
--- a/apps/space/Dockerfile.space
+++ b/apps/space/Dockerfile.space
@@ -28,35 +28,36 @@ FROM base AS installer
ENV NODE_ENV=production
# Public envs required at build time (pick up via process.env)
-ARG NEXT_PUBLIC_API_BASE_URL=""
-ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
-ARG NEXT_PUBLIC_API_BASE_PATH="/api"
-ENV NEXT_PUBLIC_API_BASE_PATH=$NEXT_PUBLIC_API_BASE_PATH
+ARG VITE_API_BASE_URL=""
+ENV VITE_API_BASE_URL=$VITE_API_BASE_URL
+ARG VITE_API_BASE_PATH="/api"
+ENV VITE_API_BASE_PATH=$VITE_API_BASE_PATH
-ARG NEXT_PUBLIC_ADMIN_BASE_URL=""
-ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL
-ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
-ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH
+ARG VITE_ADMIN_BASE_URL=""
+ENV VITE_ADMIN_BASE_URL=$VITE_ADMIN_BASE_URL
+ARG VITE_ADMIN_BASE_PATH="/god-mode"
+ENV VITE_ADMIN_BASE_PATH=$VITE_ADMIN_BASE_PATH
-ARG NEXT_PUBLIC_SPACE_BASE_URL=""
-ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL
-ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
-ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH
+ARG VITE_SPACE_BASE_URL=""
+ENV VITE_SPACE_BASE_URL=$VITE_SPACE_BASE_URL
+ARG VITE_SPACE_BASE_PATH="/spaces"
+ENV VITE_SPACE_BASE_PATH=$VITE_SPACE_BASE_PATH
-ARG NEXT_PUBLIC_LIVE_BASE_URL=""
-ENV NEXT_PUBLIC_LIVE_BASE_URL=$NEXT_PUBLIC_LIVE_BASE_URL
-ARG NEXT_PUBLIC_LIVE_BASE_PATH="/live"
-ENV NEXT_PUBLIC_LIVE_BASE_PATH=$NEXT_PUBLIC_LIVE_BASE_PATH
+ARG VITE_LIVE_BASE_URL=""
+ENV VITE_LIVE_BASE_URL=$VITE_LIVE_BASE_URL
+ARG VITE_LIVE_BASE_PATH="/live"
+ENV VITE_LIVE_BASE_PATH=$VITE_LIVE_BASE_PATH
-ARG NEXT_PUBLIC_WEB_BASE_URL=""
-ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL
-ARG NEXT_PUBLIC_WEB_BASE_PATH=""
-ENV NEXT_PUBLIC_WEB_BASE_PATH=$NEXT_PUBLIC_WEB_BASE_PATH
+ARG VITE_WEB_BASE_URL=""
+ENV VITE_WEB_BASE_URL=$VITE_WEB_BASE_URL
+ARG VITE_WEB_BASE_PATH=""
+ENV VITE_WEB_BASE_PATH=$VITE_WEB_BASE_PATH
-ARG NEXT_PUBLIC_WEBSITE_URL="https://plane.so"
-ENV NEXT_PUBLIC_WEBSITE_URL=$NEXT_PUBLIC_WEBSITE_URL
-ARG NEXT_PUBLIC_SUPPORT_EMAIL="support@plane.so"
-ENV NEXT_PUBLIC_SUPPORT_EMAIL=$NEXT_PUBLIC_SUPPORT_EMAIL
+ARG VITE_WEBSITE_URL="https://plane.so"
+ENV VITE_WEBSITE_URL=$VITE_WEBSITE_URL
+
+ARG VITE_SUPPORT_EMAIL="support@plane.so"
+ENV VITE_SUPPORT_EMAIL=$VITE_SUPPORT_EMAIL
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
diff --git a/apps/space/app/entry.client.tsx b/apps/space/app/entry.client.tsx
new file mode 100644
index 0000000000..82ea2d9381
--- /dev/null
+++ b/apps/space/app/entry.client.tsx
@@ -0,0 +1,34 @@
+/* eslint-disable import/order */
+import * as Sentry from "@sentry/react-router";
+import { startTransition, StrictMode } from "react";
+import { hydrateRoot } from "react-dom/client";
+import { HydratedRouter } from "react-router/dom";
+
+Sentry.init({
+ dsn: process.env.VITE_SENTRY_DSN,
+ environment: process.env.VITE_SENTRY_ENVIRONMENT,
+ sendDefaultPii: process.env.VITE_SENTRY_SEND_DEFAULT_PII ? process.env.VITE_SENTRY_SEND_DEFAULT_PII === "1" : false,
+ release: process.env.VITE_APP_VERSION,
+ tracesSampleRate: process.env.VITE_SENTRY_TRACES_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_TRACES_SAMPLE_RATE)
+ : 0.1,
+ profilesSampleRate: process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE)
+ : 0.1,
+ replaysSessionSampleRate: process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE)
+ : 0.1,
+ replaysOnErrorSampleRate: process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE)
+ : 1.0,
+ integrations: [],
+});
+
+startTransition(() => {
+ hydrateRoot(
+ document,
+
+
+
+ );
+});
diff --git a/apps/space/app/issues/[anchor]/layout.tsx b/apps/space/app/issues/[anchor]/layout.tsx
index a37c8b23f6..60a171bcf5 100644
--- a/apps/space/app/issues/[anchor]/layout.tsx
+++ b/apps/space/app/issues/[anchor]/layout.tsx
@@ -33,7 +33,7 @@ export async function loader({ params }: Route.LoaderArgs) {
}
try {
- const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/public/anchor/${anchor}/meta/`);
+ const response = await fetch(`${process.env.VITE_API_BASE_URL}/api/public/anchor/${anchor}/meta/`);
if (!response.ok) {
return { metadata: null };
diff --git a/apps/space/app/root.tsx b/apps/space/app/root.tsx
index 25f3e44710..85c385d095 100644
--- a/apps/space/app/root.tsx
+++ b/apps/space/app/root.tsx
@@ -1,3 +1,4 @@
+import * as Sentry from "@sentry/react-router";
import { Links, Meta, Outlet, Scripts } from "react-router";
import type { HeadersFunction, LinksFunction } from "react-router";
// assets
@@ -79,6 +80,10 @@ export function HydrateFallback() {
);
}
-export function ErrorBoundary() {
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+ if (error) {
+ Sentry.captureException(error);
+ }
+
return ;
}
diff --git a/apps/space/helpers/authentication.helper.tsx b/apps/space/helpers/authentication.helper.tsx
index b4878b12c5..d2472665de 100644
--- a/apps/space/helpers/authentication.helper.tsx
+++ b/apps/space/helpers/authentication.helper.tsx
@@ -1,6 +1,6 @@
import Link from "next/link";
// helpers
-import { SUPPORT_EMAIL } from "./common.helper";
+import { SUPPORT_EMAIL } from "@plane/constants";
export enum EPageTypes {
INIT = "INIT",
diff --git a/apps/space/helpers/common.helper.ts b/apps/space/helpers/common.helper.ts
index 787a64f546..1f2c22b024 100644
--- a/apps/space/helpers/common.helper.ts
+++ b/apps/space/helpers/common.helper.ts
@@ -1,4 +1,2 @@
-export const SUPPORT_EMAIL = process.env.NEXT_PUBLIC_SUPPORT_EMAIL || "";
-
export const resolveGeneralTheme = (resolvedTheme: string | undefined) =>
resolvedTheme?.includes("light") ? "light" : resolvedTheme?.includes("dark") ? "dark" : "system";
diff --git a/apps/space/package.json b/apps/space/package.json
index d22651da17..32027ee652 100644
--- a/apps/space/package.json
+++ b/apps/space/package.json
@@ -32,10 +32,10 @@
"@popperjs/core": "^2.11.8",
"@react-router/node": "^7.9.3",
"@react-router/serve": "^7.9.5",
+ "@sentry/react-router": "catalog:",
"axios": "catalog:",
"clsx": "^2.0.0",
"date-fns": "^4.1.0",
- "dotenv": "^16.4.5",
"isbot": "^5.1.31",
"lodash-es": "catalog:",
"lucide-react": "catalog:",
diff --git a/apps/space/react-router.config.ts b/apps/space/react-router.config.ts
index 6b2adf937e..78a1743988 100644
--- a/apps/space/react-router.config.ts
+++ b/apps/space/react-router.config.ts
@@ -1,7 +1,7 @@
import type { Config } from "@react-router/dev/config";
import { joinUrlPath } from "@plane/utils";
-const basePath = joinUrlPath(process.env.NEXT_PUBLIC_SPACE_BASE_PATH ?? "", "/") ?? "/";
+const basePath = joinUrlPath(process.env.VITE_SPACE_BASE_PATH ?? "", "/") ?? "/";
export default {
appDirectory: "app",
diff --git a/apps/space/vite.config.ts b/apps/space/vite.config.ts
index ce1389e81d..98cfc4e7d1 100644
--- a/apps/space/vite.config.ts
+++ b/apps/space/vite.config.ts
@@ -1,26 +1,23 @@
import path from "node:path";
import { reactRouter } from "@react-router/dev/vite";
-import dotenv from "dotenv";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import { joinUrlPath } from "@plane/utils";
-dotenv.config({ path: path.resolve(__dirname, ".env") });
-
-// Automatically expose all environment variables prefixed with NEXT_PUBLIC_
-const publicEnv = Object.keys(process.env)
- .filter((key) => key.startsWith("NEXT_PUBLIC_"))
- .reduce>((acc, key) => {
- acc[key] = process.env[key] ?? "";
- return acc;
+// Expose only vars starting with VITE_
+const viteEnv = Object.keys(process.env)
+ .filter((k) => k.startsWith("VITE_"))
+ .reduce>((a, k) => {
+ a[k] = process.env[k] ?? "";
+ return a;
}, {});
-const basePath = joinUrlPath(process.env.NEXT_PUBLIC_SPACE_BASE_PATH ?? "", "/") ?? "/";
+const basePath = joinUrlPath(process.env.VITE_SPACE_BASE_PATH ?? "", "/") ?? "/";
export default defineConfig(() => ({
base: basePath,
define: {
- "process.env": JSON.stringify(publicEnv),
+ "process.env": JSON.stringify(viteEnv),
},
build: {
assetsInlineLimit: 0,
diff --git a/apps/web/.env.example b/apps/web/.env.example
index 15d7a36a9d..59663aa673 100644
--- a/apps/web/.env.example
+++ b/apps/web/.env.example
@@ -1,12 +1,12 @@
-NEXT_PUBLIC_API_BASE_URL="http://localhost:8000"
+VITE_API_BASE_URL="http://localhost:8000"
-NEXT_PUBLIC_WEB_BASE_URL="http://localhost:3000"
+VITE_WEB_BASE_URL="http://localhost:3000"
-NEXT_PUBLIC_ADMIN_BASE_URL="http://localhost:3001"
-NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
+VITE_ADMIN_BASE_URL="http://localhost:3001"
+VITE_ADMIN_BASE_PATH="/god-mode"
-NEXT_PUBLIC_SPACE_BASE_URL="http://localhost:3002"
-NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
+VITE_SPACE_BASE_URL="http://localhost:3002"
+VITE_SPACE_BASE_PATH="/spaces"
-NEXT_PUBLIC_LIVE_BASE_URL="http://localhost:3100"
-NEXT_PUBLIC_LIVE_BASE_PATH="/live"
+VITE_LIVE_BASE_URL="http://localhost:3100"
+VITE_LIVE_BASE_PATH="/live"
diff --git a/apps/web/Dockerfile.web b/apps/web/Dockerfile.web
index ff5ef65dd1..b08881cf4d 100644
--- a/apps/web/Dockerfile.web
+++ b/apps/web/Dockerfile.web
@@ -41,29 +41,29 @@ COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store CI=true pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store
-ARG NEXT_PUBLIC_API_BASE_URL=""
-ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
+ARG VITE_API_BASE_URL=""
+ENV VITE_API_BASE_URL=$VITE_API_BASE_URL
-ARG NEXT_PUBLIC_ADMIN_BASE_URL=""
-ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL
+ARG VITE_ADMIN_BASE_URL=""
+ENV VITE_ADMIN_BASE_URL=$VITE_ADMIN_BASE_URL
-ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
-ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH
+ARG VITE_ADMIN_BASE_PATH="/god-mode"
+ENV VITE_ADMIN_BASE_PATH=$VITE_ADMIN_BASE_PATH
-ARG NEXT_PUBLIC_LIVE_BASE_URL=""
-ENV NEXT_PUBLIC_LIVE_BASE_URL=$NEXT_PUBLIC_LIVE_BASE_URL
+ARG VITE_LIVE_BASE_URL=""
+ENV VITE_LIVE_BASE_URL=$VITE_LIVE_BASE_URL
-ARG NEXT_PUBLIC_LIVE_BASE_PATH="/live"
-ENV NEXT_PUBLIC_LIVE_BASE_PATH=$NEXT_PUBLIC_LIVE_BASE_PATH
+ARG VITE_LIVE_BASE_PATH="/live"
+ENV VITE_LIVE_BASE_PATH=$VITE_LIVE_BASE_PATH
-ARG NEXT_PUBLIC_SPACE_BASE_URL=""
-ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL
+ARG VITE_SPACE_BASE_URL=""
+ENV VITE_SPACE_BASE_URL=$VITE_SPACE_BASE_URL
-ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
-ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH
+ARG VITE_SPACE_BASE_PATH="/spaces"
+ENV VITE_SPACE_BASE_PATH=$VITE_SPACE_BASE_PATH
-ARG NEXT_PUBLIC_WEB_BASE_URL=""
-ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL
+ARG VITE_WEB_BASE_URL=""
+ENV VITE_WEB_BASE_URL=$VITE_WEB_BASE_URL
ENV NEXT_TELEMETRY_DISABLED=1
ENV TURBO_TELEMETRY_DISABLED=1
diff --git a/apps/web/app/(all)/layout.preload.tsx b/apps/web/app/(all)/layout.preload.tsx
index e44c0e4002..266df5a1cc 100644
--- a/apps/web/app/(all)/layout.preload.tsx
+++ b/apps/web/app/(all)/layout.preload.tsx
@@ -9,11 +9,11 @@
// };
// const urls = [
-// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/instances/`,
-// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/`,
-// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/profile/`,
-// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/settings/`,
-// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/users/me/workspaces/?v=${Date.now()}`,
+// `${process.env.VITE_API_BASE_URL}/api/instances/`,
+// `${process.env.VITE_API_BASE_URL}/api/users/me/`,
+// `${process.env.VITE_API_BASE_URL}/api/users/me/profile/`,
+// `${process.env.VITE_API_BASE_URL}/api/users/me/settings/`,
+// `${process.env.VITE_API_BASE_URL}/api/users/me/workspaces/?v=${Date.now()}`,
// ];
// urls.forEach((url) => preloadItem(url));
diff --git a/apps/web/app/entry.client.tsx b/apps/web/app/entry.client.tsx
new file mode 100644
index 0000000000..82ea2d9381
--- /dev/null
+++ b/apps/web/app/entry.client.tsx
@@ -0,0 +1,34 @@
+/* eslint-disable import/order */
+import * as Sentry from "@sentry/react-router";
+import { startTransition, StrictMode } from "react";
+import { hydrateRoot } from "react-dom/client";
+import { HydratedRouter } from "react-router/dom";
+
+Sentry.init({
+ dsn: process.env.VITE_SENTRY_DSN,
+ environment: process.env.VITE_SENTRY_ENVIRONMENT,
+ sendDefaultPii: process.env.VITE_SENTRY_SEND_DEFAULT_PII ? process.env.VITE_SENTRY_SEND_DEFAULT_PII === "1" : false,
+ release: process.env.VITE_APP_VERSION,
+ tracesSampleRate: process.env.VITE_SENTRY_TRACES_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_TRACES_SAMPLE_RATE)
+ : 0.1,
+ profilesSampleRate: process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE)
+ : 0.1,
+ replaysSessionSampleRate: process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE)
+ : 0.1,
+ replaysOnErrorSampleRate: process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE
+ ? parseFloat(process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE)
+ : 1.0,
+ integrations: [],
+});
+
+startTransition(() => {
+ hydrateRoot(
+ document,
+
+
+
+ );
+});
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index d73d82d0dd..4cbf9aca92 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -50,7 +50,7 @@ export const meta = () => [
];
export default function RootLayout({ children }: { children: React.ReactNode }) {
- const isSessionRecorderEnabled = parseInt(process.env.NEXT_PUBLIC_ENABLE_SESSION_RECORDER || "0");
+ const isSessionRecorderEnabled = parseInt(process.env.VITE_ENABLE_SESSION_RECORDER || "0");
return (
@@ -86,16 +86,16 @@ export default function RootLayout({ children }: { children: React.ReactNode })
- {process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN && (
-
+ {process.env.VITE_PLAUSIBLE_DOMAIN && (
+
)}
- {!!isSessionRecorderEnabled && process.env.NEXT_PUBLIC_SESSION_RECORDER_KEY && (
+ {!!isSessionRecorderEnabled && process.env.VITE_SESSION_RECORDER_KEY && (
)}