Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/admin/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
VITE_API_BASE_URL="http://localhost:8000"

VITE_WEB_BASE_URL="http://localhost:3000"
VITE_WEB_BASE_PATH=""

VITE_ADMIN_BASE_URL="http://localhost:3001"
VITE_ADMIN_BASE_PATH="/god-mode"
Expand Down
3 changes: 2 additions & 1 deletion apps/admin/Dockerfile.admin
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ ENV VITE_API_BASE_PATH=$VITE_API_BASE_PATH

ARG VITE_ADMIN_BASE_URL=""
ENV VITE_ADMIN_BASE_URL=$VITE_ADMIN_BASE_URL
ARG VITE_ADMIN_BASE_PATH="/god-mode"
ARG VITE_ADMIN_BASE_PATH="/plane/god-mode"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Breaking default: VITE_ADMIN_BASE_PATH changed from /god-mode to /plane/god-mode

The PR states backward compatibility is preserved, but changing this default means existing deployments that rely on the previous /god-mode default will break without explicitly overriding the build arg. Consider keeping the original default and letting subpath deployments override it:

-ARG VITE_ADMIN_BASE_PATH="/plane/god-mode"
+ARG VITE_ADMIN_BASE_PATH="/god-mode"

The docker-compose-subpath.yml already passes VITE_ADMIN_BASE_PATH: "/plane/god-mode" explicitly (Line 13), so subpath deployments are unaffected.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ARG VITE_ADMIN_BASE_PATH="/plane/god-mode"
ARG VITE_ADMIN_BASE_PATH="/god-mode"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/admin/Dockerfile.admin` at line 38, The Dockerfile's build ARG
VITE_ADMIN_BASE_PATH was changed to "/plane/god-mode", breaking the previous
default; revert ARG VITE_ADMIN_BASE_PATH back to "/god-mode" so existing
deployments stay compatible, and keep docker-compose-subpath (which already
overrides VITE_ADMIN_BASE_PATH) to provide the subpath "/plane/god-mode" for
those deployments; update the ARG declaration (VITE_ADMIN_BASE_PATH) to the
original default and ensure documentation/comments note that
docker-compose-subpath.yml supplies the subpath override.

ENV VITE_ADMIN_BASE_PATH=$VITE_ADMIN_BASE_PATH

ARG VITE_SPACE_BASE_URL=""
Expand Down Expand Up @@ -78,6 +78,7 @@ RUN pnpm turbo run build --filter=admin
FROM nginx:1.29-alpine AS production

COPY apps/admin/nginx/nginx.conf /etc/nginx/nginx.conf
RUN rm -f /etc/nginx/conf.d/default.conf
COPY --from=installer /app/apps/admin/build/client /usr/share/nginx/html/god-mode

EXPOSE 3000
Expand Down
4 changes: 2 additions & 2 deletions apps/admin/app/(all)/(dashboard)/sidebar-help-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { observer } from "mobx-react";
import Link from "next/link";
import { HelpCircle, MoveLeft } from "lucide-react";
import { Transition } from "@headlessui/react";
import { WEB_BASE_URL } from "@plane/constants";
import { WEB_URL } from "@plane/constants";
// plane internal packages
import { DiscordIcon, GithubIcon, NewTabIcon, PageIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
Expand Down Expand Up @@ -45,7 +45,7 @@ export const AdminSidebarHelpSection = observer(function AdminSidebarHelpSection
// refs
const helpOptionsRef = useRef<HTMLDivElement | null>(null);

const redirectionLink = encodeURI(WEB_BASE_URL + "/");
const redirectionLink = WEB_URL;

return (
<div
Expand Down
4 changes: 2 additions & 2 deletions apps/admin/app/(all)/(dashboard)/workspace/create/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Link from "next/link";
import { useRouter } from "next/navigation";
import { Controller, useForm } from "react-hook-form";
// plane imports
import { WEB_BASE_URL, ORGANIZATION_SIZE, RESTRICTED_URLS } from "@plane/constants";
import { WEB_URL, ORGANIZATION_SIZE, RESTRICTED_URLS } from "@plane/constants";
import { Button, getButtonStyling } from "@plane/propel/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import { InstanceWorkspaceService } from "@plane/services";
Expand Down Expand Up @@ -43,7 +43,7 @@ export function WorkspaceCreateForm() {
formState: { errors, isSubmitting, isValid },
} = useForm<IWorkspace>({ defaultValues, mode: "onChange" });
// derived values
const workspaceBaseURL = encodeURI(WEB_BASE_URL || window.location.origin + "/");
const workspaceBaseURL = WEB_URL || encodeURI(window.location.origin + "/");

const handleCreateWorkspace = async (formData: IWorkspace) => {
await instanceWorkspaceService
Expand Down
15 changes: 13 additions & 2 deletions apps/admin/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* See the LICENSE file for details.
*/

import type { ReactNode } from "react";
import React, { type ReactNode } from "react";
import { Links, Meta, Outlet, Scripts } from "react-router";
import type { LinksFunction } from "react-router";
import * as Sentry from "@sentry/react-router";
Expand All @@ -14,6 +14,7 @@ import favicon32 from "@/app/assets/favicon/favicon-32x32.png?url";
import faviconIco from "@/app/assets/favicon/favicon.ico?url";
import { LogoSpinner } from "@/components/common/logo-spinner";
import globalStyles from "@/styles/globals.css?url";
import { joinUrlPath } from "@plane/utils";
import { AppProviders } from "@/providers";
import type { Route } from "./+types/root";
// fonts
Expand All @@ -25,13 +26,15 @@ import "@fontsource/ibm-plex-mono";
const APP_TITLE = "Plane | Simple, extensible, open-source project management tool.";
const APP_DESCRIPTION =
"Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.";
const WEB_BASE_PATH =
(typeof import.meta !== "undefined" && import.meta.env?.BASE_URL) || process.env.VITE_ADMIN_BASE_PATH || "/god-mode";

export const links: LinksFunction = () => [
{ rel: "apple-touch-icon", sizes: "180x180", href: appleTouchIcon },
{ rel: "icon", type: "image/png", sizes: "32x32", href: favicon32 },
{ rel: "icon", type: "image/png", sizes: "16x16", href: favicon16 },
{ rel: "shortcut icon", href: faviconIco },
{ rel: "manifest", href: `/site.webmanifest.json` },
{ rel: "manifest", href: joinUrlPath(WEB_BASE_PATH, "site.webmanifest.json") },
{ rel: "stylesheet", href: globalStyles },
{
rel: "preload",
Expand Down Expand Up @@ -82,6 +85,14 @@ export default function Root() {
}

export function HydrateFallback() {
const [isMounted, setIsMounted] = React.useState(false);

React.useEffect(() => {
setIsMounted(true);
}, []);

if (typeof window === "undefined" || !isMounted) return <div />;

return (
<div className="relative flex h-screen w-full items-center justify-center">
<LogoSpinner />
Expand Down
9 changes: 4 additions & 5 deletions apps/admin/core/components/workspace/list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { observer } from "mobx-react";

// plane internal packages
import { WEB_BASE_URL } from "@plane/constants";
import { WEB_URL } from "@plane/constants";
import { NewTabIcon } from "@plane/propel/icons";
import { Tooltip } from "@plane/propel/tooltip";
import { getFileURL } from "@plane/utils";
Expand All @@ -28,16 +28,15 @@ export const WorkspaceListItem = observer(function WorkspaceListItem({ workspace
return (
<a
key={workspaceId}
href={`${WEB_BASE_URL}/${encodeURIComponent(workspace.slug)}`}
href={`${WEB_URL}/${encodeURIComponent(workspace.slug)}`}
target="_blank"
className="group flex items-center justify-between p-3 gap-2.5 truncate border border-subtle hover:border-subtle-1 bg-layer-1 hover:bg-layer-1-hover hover:shadow-raised-100 rounded-lg"
rel="noreferrer"
>
<div className="flex items-start gap-4">
<span
className={`relative flex h-8 w-8 flex-shrink-0 items-center justify-center p-2 mt-1 text-11 uppercase ${
!workspace?.logo_url && "rounded-lg bg-accent-primary text-on-color"
}`}
className={`relative flex h-8 w-8 flex-shrink-0 items-center justify-center p-2 mt-1 text-11 uppercase ${!workspace?.logo_url && "rounded-lg bg-accent-primary text-on-color"
}`}
>
{workspace?.logo_url && workspace.logo_url !== "" ? (
<img
Expand Down
11 changes: 10 additions & 1 deletion apps/admin/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@ http {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-XSS-Protection "1; mode=block" always;

location / {
location = / {
return 200 "healthy\n";
}

location = /god-mode {
root /usr/share/nginx/html;
try_files /god-mode/index.html =404;
}

location /god-mode/ {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /god-mode/index.html;
Expand Down
12 changes: 10 additions & 2 deletions apps/admin/public/site.webmanifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
"background_color": "#f9fafb",
"theme_color": "#3f76ff",
"icons": [
{ "src": "/favicon/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/favicon/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" }
{
"src": "favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "favicon/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
2 changes: 1 addition & 1 deletion apps/admin/react-router.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Config } from "@react-router/dev/config";
import { joinUrlPath } from "@plane/utils";

const basePath = joinUrlPath(process.env.VITE_ADMIN_BASE_PATH ?? "", "/") ?? "/";
const basePath = (joinUrlPath(process.env.VITE_ADMIN_BASE_PATH ?? "") ?? "/").replace(/\/$/, "") || "/";

export default {
appDirectory: "app",
Expand Down
3 changes: 2 additions & 1 deletion apps/api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ USE_MINIO=0



# Email redirections and minio domain settings
# Email redirections and minio domain settings (include subpath if any, e.g., http://localhost:3000/plane)
WEB_URL="http://localhost:8000"

# Gunicorn Workers
Expand All @@ -58,6 +58,7 @@ SPACE_BASE_URL="http://localhost:3002"
SPACE_BASE_PATH="/spaces"

APP_BASE_URL="http://localhost:3000"
# Base path for the app (e.g., /plane)
APP_BASE_PATH=""

LIVE_BASE_URL="http://localhost:3100"
Expand Down
12 changes: 10 additions & 2 deletions apps/api/plane/authentication/utils/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,18 @@ def base_host(

# App Redirection
if is_app:
app_base_path = getattr(settings, "APP_BASE_PATH", None)
if not isinstance(app_base_path, str):
app_base_path = "/"
if not app_base_path.startswith("/"):
app_base_path = "/" + app_base_path
if not app_base_path.endswith("/"):
app_base_path += "/"

if settings.APP_BASE_URL:
return settings.APP_BASE_URL
return settings.APP_BASE_URL + app_base_path
else:
return base_origin
return base_origin + app_base_path

return base_origin

Expand Down
9 changes: 8 additions & 1 deletion apps/api/plane/settings/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
from botocore.exceptions import ClientError
from urllib.parse import quote

# Django imports
from django.conf import settings

# Module imports
from plane.utils.exception_logger import log_exception
from storages.backends.s3boto3 import S3Boto3Storage
Expand Down Expand Up @@ -48,7 +51,11 @@ def __init__(self, request=None):
aws_access_key_id=self.aws_access_key_id,
aws_secret_access_key=self.aws_secret_access_key,
region_name=self.aws_region,
endpoint_url=(f"{endpoint_protocol}://{request.get_host()}" if request else self.aws_s3_endpoint_url),
endpoint_url=(
f"{endpoint_protocol}://{request.get_host()}{settings.APP_BASE_PATH}"
if request
else self.aws_s3_endpoint_url
),
config=boto3.session.Config(signature_version="s3v4"),
)
else:
Expand Down
12 changes: 10 additions & 2 deletions apps/api/plane/utils/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,18 @@ def base_host(

# App Redirection
if is_app:
app_base_path = getattr(settings, "APP_BASE_PATH", None)
if not isinstance(app_base_path, str):
app_base_path = "/"
if not app_base_path.startswith("/"):
app_base_path = "/" + app_base_path
if not app_base_path.endswith("/"):
app_base_path += "/"

if settings.APP_BASE_URL:
return settings.APP_BASE_URL
return settings.APP_BASE_URL + app_base_path
else:
return base_origin
return base_origin + app_base_path

return base_origin

Expand Down
2 changes: 1 addition & 1 deletion apps/live/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"private": true,
"type": "module",
"scripts": {
"build": "tsc --noEmit && tsdown",
"build": "tsdown",
"dev": "tsdown --watch --onSuccess \"node --env-file=.env .\"",
"start": "node --env-file=.env .",
"test": "vitest run",
Expand Down
1 change: 1 addition & 0 deletions apps/space/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
VITE_API_BASE_URL="http://localhost:8000"

VITE_WEB_BASE_URL="http://localhost:3000"
VITE_WEB_BASE_PATH=""

VITE_ADMIN_BASE_URL="http://localhost:3001"
VITE_ADMIN_BASE_PATH="/god-mode"
Expand Down
9 changes: 9 additions & 0 deletions apps/space/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* See the LICENSE file for details.
*/

import React from "react";
import * as Sentry from "@sentry/react-router";
import { Links, Meta, Outlet, Scripts } from "react-router";
// assets
Expand Down Expand Up @@ -89,6 +90,14 @@ export default function Root() {
}

export function HydrateFallback() {
const [isMounted, setIsMounted] = React.useState(false);

React.useEffect(() => {
setIsMounted(true);
}, []);

if (typeof window === "undefined" || !isMounted) return <div />;

return (
<div className="bg-surface-1 relative flex h-screen w-full items-center justify-center">
<LogoSpinner />
Expand Down
12 changes: 10 additions & 2 deletions apps/space/public/site.webmanifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
"background_color": "#f9fafb",
"theme_color": "#3f76ff",
"icons": [
{ "src": "/favicon/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/favicon/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" }
{
"src": "favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "favicon/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
2 changes: 1 addition & 1 deletion apps/space/react-router.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Config } from "@react-router/dev/config";
import { joinUrlPath } from "@plane/utils";

const basePath = joinUrlPath(process.env.VITE_SPACE_BASE_PATH ?? "", "/") ?? "/";
const basePath = (joinUrlPath(process.env.VITE_SPACE_BASE_PATH ?? "") ?? "/").replace(/\/$/, "") || "/";

export default {
appDirectory: "app",
Expand Down
1 change: 1 addition & 0 deletions apps/web/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
VITE_API_BASE_URL="http://localhost:8000"

VITE_WEB_BASE_URL="http://localhost:3000"
VITE_WEB_BASE_PATH=""

VITE_ADMIN_BASE_URL="http://localhost:3001"
VITE_ADMIN_BASE_PATH="/god-mode"
Expand Down
3 changes: 3 additions & 0 deletions apps/web/Dockerfile.web
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ ENV VITE_SPACE_BASE_PATH=$VITE_SPACE_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

ENV NEXT_TELEMETRY_DISABLED=1
ENV TURBO_TELEMETRY_DISABLED=1

Expand Down
7 changes: 4 additions & 3 deletions apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import "@/styles/globals.css";
import { SITE_DESCRIPTION, SITE_NAME } from "@plane/constants";

// helpers
import { cn } from "@plane/utils";
import { cn, joinUrlPath } from "@plane/utils";

// assets
import favicon16 from "@/app/assets/favicon/favicon-16x16.png?url";
Expand Down Expand Up @@ -57,14 +57,16 @@ export const meta = () => [

export default function RootLayout({ children }: { children: React.ReactNode }) {
const isSessionRecorderEnabled = parseInt(process.env.VITE_ENABLE_SESSION_RECORDER || "0");
const WEB_BASE_PATH =
(typeof import.meta !== "undefined" && import.meta.env?.BASE_URL) || process.env.VITE_WEB_BASE_PATH || "/";

return (
<html lang="en">
<head>
<meta name="theme-color" content="#fff" />
<link rel="icon" type="image/png" sizes="32x32" href={favicon32} />
<link rel="icon" type="image/png" sizes="16x16" href={favicon16} />
<link rel="manifest" href="/site.webmanifest.json" />
<link rel="manifest" href={joinUrlPath(WEB_BASE_PATH, "site.webmanifest.json")} />
Comment thread
coderabbitai[bot] marked this conversation as resolved.
<link rel="shortcut icon" href={faviconIco} />
{/* Meta info for PWA */}
<meta name="application-name" content="Plane" />
Expand All @@ -76,7 +78,6 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<link rel="apple-touch-icon" href={icon512} />
<link rel="apple-touch-icon" sizes="180x180" href={icon180} />
<link rel="apple-touch-icon" sizes="512x512" href={icon512} />
<link rel="manifest" href="/manifest.json" />
</head>
<body>
<div id="context-menu-portal" />
Expand Down
Loading