Skip to content
Draft
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b18aa45
feat: admin react-router migration
lifeiscontent Oct 9, 2025
97083c9
chore: update dependencies and improve server configuration
prateekshourya29 Oct 10, 2025
35f87a5
feat: add ensureTrailingSlash utility and integrate into Link and use…
prateekshourya29 Oct 10, 2025
fa73c33
refactor: remove old error page and implement ErrorBoundary in root c…
prateekshourya29 Oct 10, 2025
c15ceb0
feat: add custom 404 page and catch-all route for improved error hand…
prateekshourya29 Oct 10, 2025
2894119
fix: update nginx server listen port from 3000 to 3001
prateekshourya29 Oct 10, 2025
a48c9fd
fix: revert nginx server listen port from 3001 back to 3000 and remov…
prateekshourya29 Oct 11, 2025
4b2cc27
fix: merge conflicts
prateekshourya29 Oct 14, 2025
57e324e
chore: update dependencies across multiple packages
prateekshourya29 Oct 14, 2025
bf6fdef
Merge branch 'preview' of github.com:makeplane/plane into feat/admin-…
prateekshourya29 Oct 14, 2025
557e146
feat: migrate to Vite with React Router and update project structure
prateekshourya29 Oct 14, 2025
edc198e
refactor: remove deprecated views layout and page components
prateekshourya29 Oct 14, 2025
263b46f
refactor: update import path for Route type in client layout
prateekshourya29 Oct 14, 2025
06ade41
fix: enable verbatim module syntax in TypeScript configuration for Re…
prateekshourya29 Oct 14, 2025
2757c4c
fix: merge conflicts
prateekshourya29 Oct 28, 2025
c5dc294
chore: clean up package dependencies and remove unused packages
prateekshourya29 Oct 28, 2025
77616d3
chore: remove unused path alias from tsconfig.json
prateekshourya29 Oct 29, 2025
67d2ba8
Merge branch 'feat/admin-react-router-migration' of github.com:makepl…
prateekshourya29 Oct 29, 2025
a748ef0
fix: merge conflicts
prateekshourya29 Oct 30, 2025
2593206
fix: space app build
prateekshourya29 Oct 31, 2025
e84254c
Merge branch 'feat/admin-react-router-migration' of github.com:makepl…
prateekshourya29 Oct 31, 2025
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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ temp/
.react-router/
build/
node_modules/
README.md
README.md
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ dev-editor
storybook-static

CLAUDE.md

build/
.react-router/
5 changes: 5 additions & 0 deletions apps/admin/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# React Router - https://github.com/remix-run/react-router-templates/blob/dc79b1a065f59f3bfd840d4ef75cc27689b611e6/default/.dockerignore
.react-router/
build/
node_modules/
README.md
1 change: 1 addition & 0 deletions apps/space/.eslintrc.js → apps/admin/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
root: true,
extends: ["@plane/eslint-config/next.js"],
ignorePatterns: ["build/**", "dist/**", ".vite/**"],
rules: {
"no-duplicate-imports": "off",
"import/no-duplicates": ["error", { "prefer-inline": false }],
Expand Down
111 changes: 47 additions & 64 deletions apps/admin/Dockerfile.admin
Original file line number Diff line number Diff line change
@@ -1,103 +1,86 @@
# syntax=docker/dockerfile:1.7
FROM node:22-alpine AS base

# Setup pnpm package manager with corepack and configure global bin directory for caching
WORKDIR /app

ENV TURBO_TELEMETRY_DISABLED=1
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
ENV CI=1

RUN corepack enable pnpm

# =========================================================================== #

# *****************************************************************************
# STAGE 1: Build the project
# *****************************************************************************
FROM base AS builder
RUN apk add --no-cache libc6-compat
WORKDIR /app

ARG TURBO_VERSION=2.5.6
RUN corepack enable pnpm && pnpm add -g turbo@${TURBO_VERSION}
RUN pnpm add -g turbo@2.5.8

COPY . .

# Create a pruned workspace for just the admin app
RUN turbo prune --scope=admin --docker

# *****************************************************************************
# STAGE 2: Install dependencies & build the project
# *****************************************************************************
FROM base AS installer

RUN apk add --no-cache libc6-compat
WORKDIR /app
# =========================================================================== #

COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN corepack enable pnpm
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm fetch --store-dir=/pnpm/store
FROM base AS installer

COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store
# Build in production mode; we still install dev deps explicitly below
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 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 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 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 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

ENV NEXT_TELEMETRY_DISABLED=1
ENV TURBO_TELEMETRY_DISABLED=1

RUN pnpm turbo run build --filter=admin
ARG NEXT_PUBLIC_WEBSITE_URL="https://plane.so"
ENV NEXT_PUBLIC_WEBSITE_URL=$NEXT_PUBLIC_WEBSITE_URL
ARG NEXT_PUBLIC_SUPPORT_EMAIL="[email protected]"
ENV NEXT_PUBLIC_SUPPORT_EMAIL=$NEXT_PUBLIC_SUPPORT_EMAIL

# *****************************************************************************
# STAGE 3: Copy the project and start it
# *****************************************************************************
FROM base AS runner
WORKDIR /app

# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer /app/apps/admin/.next/standalone ./
COPY --from=installer /app/apps/admin/.next/static ./apps/admin/.next/static
COPY --from=installer /app/apps/admin/public ./apps/admin/public

ARG NEXT_PUBLIC_API_BASE_URL=""
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL

ARG NEXT_PUBLIC_ADMIN_BASE_URL=""
ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml

ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH
# Fetch dependencies to cache store, then install offline with dev deps
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm fetch --store-dir=/pnpm/store
COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store --prod=false

ARG NEXT_PUBLIC_SPACE_BASE_URL=""
ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL
# Build only the admin package
RUN pnpm turbo run build --filter=admin

ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH
# =========================================================================== #

ARG NEXT_PUBLIC_WEB_BASE_URL=""
ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL
FROM nginx:1.27-alpine AS production

ENV NEXT_TELEMETRY_DISABLED=1
ENV TURBO_TELEMETRY_DISABLED=1
COPY apps/admin/nginx/nginx.conf /etc/nginx/nginx.conf
COPY --from=installer /app/apps/admin/build/client /usr/share/nginx/html

EXPOSE 3000

CMD ["node", "apps/admin/server.js"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -fsS http://127.0.0.1:3000/ >/dev/null || exit 1

CMD ["nginx", "-g", "daemon off;"]
4 changes: 2 additions & 2 deletions apps/admin/app/(all)/(dashboard)/ai/form.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import type { FC } from "react";

import { useForm } from "react-hook-form";
import { Lightbulb } from "lucide-react";
import { Button } from "@plane/propel/button";
Expand All @@ -17,7 +17,7 @@ type IInstanceAIForm = {

type AIFormValues = Record<TInstanceAIConfigurationKeys, string>;

export const InstanceAIForm: FC<IInstanceAIForm> = (props) => {
export const InstanceAIForm: React.FC<IInstanceAIForm> = (props) => {
const { config } = props;
// store
const { updateInstanceConfigurations } = useInstance();
Expand Down
10 changes: 0 additions & 10 deletions apps/admin/app/(all)/(dashboard)/ai/layout.tsx

This file was deleted.

5 changes: 4 additions & 1 deletion apps/admin/app/(all)/(dashboard)/ai/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { Loader } from "@plane/ui";
// hooks
import { useInstance } from "@/hooks/store";
// components
import type { Route } from "./+types/page";
import { InstanceAIForm } from "./form";

const InstanceAIPage = observer(() => {
const InstanceAIPage = observer<React.FC<Route.ComponentProps>>(() => {
// store
const { fetchInstanceConfigurations, formattedConfig } = useInstance();

Expand Down Expand Up @@ -42,4 +43,6 @@ const InstanceAIPage = observer(() => {
);
});

export const meta: Route.MetaFunction = () => [{ title: "Artificial Intelligence Settings - God Mode" }];

export default InstanceAIPage;
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";

import type { FC } from "react";
import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
Expand Down Expand Up @@ -29,7 +28,7 @@ type Props = {

type GithubConfigFormValues = Record<TInstanceGithubAuthenticationConfigurationKeys, string>;

export const InstanceGithubConfigForm: FC<Props> = (props) => {
export const InstanceGithubConfigForm: React.FC<Props> = (props) => {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
Expand Down
10 changes: 0 additions & 10 deletions apps/admin/app/(all)/(dashboard)/authentication/github/layout.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
import { resolveGeneralTheme } from "@plane/utils";
// components
import githubLightModeImage from "@/app/assets/logos/github-black.png?url";
import githubDarkModeImage from "@/app/assets/logos/github-white.png?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
// icons
import githubLightModeImage from "@/public/logos/github-black.png";
import githubDarkModeImage from "@/public/logos/github-white.png";
// local components
import type { Route } from "./+types/page";
import { InstanceGithubConfigForm } from "./form";

const InstanceGithubAuthenticationPage = observer(() => {
const InstanceGithubAuthenticationPage = observer<React.FC<Route.ComponentProps>>(() => {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
Expand Down Expand Up @@ -111,4 +112,6 @@ const InstanceGithubAuthenticationPage = observer(() => {
);
});

export const meta: Route.MetaFunction = () => [{ title: "GitHub Authentication - God Mode" }];

export default InstanceGithubAuthenticationPage;
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { FC } from "react";
import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
Expand All @@ -25,7 +24,7 @@ type Props = {

type GitlabConfigFormValues = Record<TInstanceGitlabAuthenticationConfigurationKeys, string>;

export const InstanceGitlabConfigForm: FC<Props> = (props) => {
export const InstanceGitlabConfigForm: React.FC<Props> = (props) => {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
Expand Down
10 changes: 0 additions & 10 deletions apps/admin/app/(all)/(dashboard)/authentication/gitlab/layout.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import useSWR from "swr";
import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
// components
import GitlabLogo from "@/app/assets/logos/gitlab-logo.svg?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
// icons
import GitlabLogo from "@/public/logos/gitlab-logo.svg";
// local components
import type { Route } from "./+types/page";
import { InstanceGitlabConfigForm } from "./form";

const InstanceGitlabAuthenticationPage = observer(() => {
const InstanceGitlabAuthenticationPage = observer<React.FC<Route.ComponentProps>>(() => {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
Expand Down Expand Up @@ -99,4 +100,6 @@ const InstanceGitlabAuthenticationPage = observer(() => {
);
});

export const meta: Route.MetaFunction = () => [{ title: "GitLab Authentication - God Mode" }];

export default InstanceGitlabAuthenticationPage;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import type { FC } from "react";

import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
Expand Down Expand Up @@ -27,7 +27,7 @@ type Props = {

type GoogleConfigFormValues = Record<TInstanceGoogleAuthenticationConfigurationKeys, string>;

export const InstanceGoogleConfigForm: FC<Props> = (props) => {
export const InstanceGoogleConfigForm: React.FC<Props> = (props) => {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
Expand Down
10 changes: 0 additions & 10 deletions apps/admin/app/(all)/(dashboard)/authentication/google/layout.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import useSWR from "swr";
import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
// components
import GoogleLogo from "@/app/assets/logos/google-logo.svg?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
// icons
import GoogleLogo from "@/public/logos/google-logo.svg";
// local components
import type { Route } from "./+types/page";
import { InstanceGoogleConfigForm } from "./form";

const InstanceGoogleAuthenticationPage = observer(() => {
const InstanceGoogleAuthenticationPage = observer<React.FC<Route.ComponentProps>>(() => {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
Expand Down Expand Up @@ -100,4 +101,6 @@ const InstanceGoogleAuthenticationPage = observer(() => {
);
});

export const meta: Route.MetaFunction = () => [{ title: "Google Authentication - God Mode" }];

export default InstanceGoogleAuthenticationPage;
10 changes: 0 additions & 10 deletions apps/admin/app/(all)/(dashboard)/authentication/layout.tsx

This file was deleted.

Loading