From 0cae8330e2905b15cc69d83bb7fcd25b21df460b Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 17 Apr 2026 14:42:14 -0600 Subject: [PATCH 01/13] chore: adjust version bump timing in synchronization workflow Update the GitHub Actions workflow to bump the version in package.json after installing dependencies, ensuring that the version is not overwritten by pnpm install. This change enhances the reliability of version synchronization for both MCP and CLI repositories. --- .github/workflows/sync-version.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/sync-version.yml b/.github/workflows/sync-version.yml index 4ef94f1a9..aad018634 100644 --- a/.github/workflows/sync-version.yml +++ b/.github/workflows/sync-version.yml @@ -23,26 +23,26 @@ jobs: run: | git clone https://x-access-token:${{ secrets.DOCS_SYNC_TOKEN }}@github.com/dokploy/mcp.git mcp-repo cd mcp-repo - - # Bump version - jq --arg v "${{ steps.get_version.outputs.version }}" '.version = $v' package.json > package.json.tmp - mv package.json.tmp package.json - + # Regenerate tools from latest OpenAPI spec npm install -g pnpm pnpm install pnpm run fetch-openapi pnpm run generate - + + # Bump version after install so pnpm install doesn't overwrite it + jq --arg v "${{ steps.get_version.outputs.version }}" '.version = $v' package.json > package.json.tmp + mv package.json.tmp package.json + git config user.name "Dokploy Bot" git config user.email "bot@dokploy.com" - + git add -A git commit -m "chore: bump version to ${{ steps.get_version.outputs.version }}" \ -m "Source: ${{ github.repository }}@${{ github.sha }}" \ -m "Release: ${{ github.event.release.html_url }}" \ --allow-empty - + git push @@ -52,18 +52,18 @@ jobs: cd cli-repo - # Bump version - if [ -f package.json ]; then - jq --arg v "${{ steps.get_version.outputs.version }}" '.version = $v' package.json > package.json.tmp - mv package.json.tmp package.json - fi - # Copy latest openapi spec and regenerate commands cp ../openapi.json ./openapi.json npm install -g pnpm pnpm install pnpm run generate + # Bump version after install so pnpm install doesn't overwrite it + if [ -f package.json ]; then + jq --arg v "${{ steps.get_version.outputs.version }}" '.version = $v' package.json > package.json.tmp + mv package.json.tmp package.json + fi + git config user.name "Dokploy Bot" git config user.email "bot@dokploy.com" From e7c581476ea8d2d7c679e6038d491f7408f71ecb Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 17 Apr 2026 14:44:04 -0600 Subject: [PATCH 02/13] feat: add workflow dispatch trigger to version synchronization workflow Enhance the GitHub Actions workflow by adding a workflow_dispatch trigger, allowing manual execution of the version synchronization process. This provides greater flexibility in managing version updates for MCP and CLI repositories. --- .github/workflows/sync-version.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sync-version.yml b/.github/workflows/sync-version.yml index aad018634..5b97d2435 100644 --- a/.github/workflows/sync-version.yml +++ b/.github/workflows/sync-version.yml @@ -3,6 +3,7 @@ name: Sync version to MCP and CLI repos on: release: types: [published] + workflow_dispatch: jobs: sync-version: From 958372c5f93cf63e0d5f2e2b7ea372606dcfee1d Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 17 Apr 2026 14:46:20 -0600 Subject: [PATCH 03/13] chore: update paths in version synchronization workflow for MCP and CLI repositories Modify the GitHub Actions workflow to clone the MCP and CLI repositories into temporary directories instead of the current directory. This change improves the organization of the workflow and ensures that the latest OpenAPI specification is correctly referenced during the synchronization process. --- .github/workflows/sync-version.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sync-version.yml b/.github/workflows/sync-version.yml index 5b97d2435..1f28265ca 100644 --- a/.github/workflows/sync-version.yml +++ b/.github/workflows/sync-version.yml @@ -22,8 +22,8 @@ jobs: - name: Sync version to MCP repository run: | - git clone https://x-access-token:${{ secrets.DOCS_SYNC_TOKEN }}@github.com/dokploy/mcp.git mcp-repo - cd mcp-repo + git clone https://x-access-token:${{ secrets.DOCS_SYNC_TOKEN }}@github.com/dokploy/mcp.git /tmp/mcp-repo + cd /tmp/mcp-repo # Regenerate tools from latest OpenAPI spec npm install -g pnpm @@ -49,12 +49,12 @@ jobs: - name: Sync version to CLI repository run: | - git clone https://x-access-token:${{ secrets.DOCS_SYNC_TOKEN }}@github.com/dokploy/cli.git cli-repo + git clone https://x-access-token:${{ secrets.DOCS_SYNC_TOKEN }}@github.com/dokploy/cli.git /tmp/cli-repo - cd cli-repo + cd /tmp/cli-repo # Copy latest openapi spec and regenerate commands - cp ../openapi.json ./openapi.json + cp ${{ github.workspace }}/openapi.json ./openapi.json npm install -g pnpm pnpm install pnpm run generate From 425fef6e282afbad8a2704ceb408bff003d789a6 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 17 Apr 2026 14:49:14 -0600 Subject: [PATCH 04/13] fix: remove 'v' prefix from version in synchronization workflow Update the version retrieval command in the GitHub Actions workflow to strip the 'v' prefix from the version number in package.json. This change ensures that the version format is consistent for downstream processes. --- .github/workflows/sync-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-version.yml b/.github/workflows/sync-version.yml index 1f28265ca..be19a2bb1 100644 --- a/.github/workflows/sync-version.yml +++ b/.github/workflows/sync-version.yml @@ -16,7 +16,7 @@ jobs: - name: Get version id: get_version run: | - VERSION=$(jq -r .version apps/dokploy/package.json) + VERSION=$(jq -r .version apps/dokploy/package.json | sed 's/^v//') echo "version=$VERSION" >> $GITHUB_OUTPUT echo "Version: $VERSION" From f7b576cbf3a9fa6be5b9e262950bee4a3c5f9c6f Mon Sep 17 00:00:00 2001 From: Sancho Godinho Date: Sat, 18 Apr 2026 04:23:15 +0530 Subject: [PATCH 05/13] Fix typo in custom entrypoint description --- .../components/dashboard/application/domains/handle-domain.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/application/domains/handle-domain.tsx b/apps/dokploy/components/dashboard/application/domains/handle-domain.tsx index 655f9d147..5edcbe3a7 100644 --- a/apps/dokploy/components/dashboard/application/domains/handle-domain.tsx +++ b/apps/dokploy/components/dashboard/application/domains/handle-domain.tsx @@ -666,7 +666,7 @@ export const AddDomain = ({ id, type, domainId = "", children }: Props) => {
Custom Entrypoint - Use custom entrypoint for domina + Use custom entrypoint for domain
"web" and/or "websecure" is used by default.
From 6f0ed89ce7d07eff4fdaeb494fef50a67327934d Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 17 Apr 2026 21:36:37 -0600 Subject: [PATCH 06/13] feat: add dashboard home page with overview and recent deployments Adds a new /dashboard/home landing with welcome header, KPI cards (deploys/24h, build, CPU, memory) and a recent deployments list. Home is now the post-login landing and the destination for permission fallback redirects across the app. Projects remains accessible from the sidebar. --- .../components/dashboard/home/show-home.tsx | 223 ++++++++++++++++++ .../components/dashboard/search-command.tsx | 2 +- .../welcome-stripe/welcome-subscription.tsx | 2 +- apps/dokploy/components/layouts/side.tsx | 7 + apps/dokploy/components/layouts/user-nav.tsx | 2 +- .../proprietary/sso/sign-in-with-sso.tsx | 2 +- apps/dokploy/pages/_error.tsx | 2 +- apps/dokploy/pages/dashboard/deployments.tsx | 2 +- apps/dokploy/pages/dashboard/docker.tsx | 2 +- apps/dokploy/pages/dashboard/home.tsx | 53 +++++ apps/dokploy/pages/dashboard/monitoring.tsx | 4 +- .../environment/[environmentId].tsx | 4 +- .../services/application/[applicationId].tsx | 2 +- .../services/compose/[composeId].tsx | 2 +- .../services/libsql/[libsqlId].tsx | 2 +- .../services/mariadb/[mariadbId].tsx | 2 +- .../services/mongo/[mongoId].tsx | 2 +- .../services/mysql/[mysqlId].tsx | 2 +- .../services/postgres/[postgresId].tsx | 2 +- .../services/redis/[redisId].tsx | 2 +- apps/dokploy/pages/dashboard/requests.tsx | 2 +- apps/dokploy/pages/dashboard/schedules.tsx | 2 +- .../pages/dashboard/settings/billing.tsx | 2 +- .../pages/dashboard/settings/cluster.tsx | 2 +- .../pages/dashboard/settings/invoices.tsx | 2 +- .../pages/dashboard/settings/server.tsx | 2 +- apps/dokploy/pages/dashboard/swarm.tsx | 2 +- apps/dokploy/pages/dashboard/traefik.tsx | 2 +- apps/dokploy/pages/index.tsx | 10 +- apps/dokploy/pages/invitation.tsx | 2 +- apps/dokploy/pages/register.tsx | 2 +- 31 files changed, 317 insertions(+), 34 deletions(-) create mode 100644 apps/dokploy/components/dashboard/home/show-home.tsx create mode 100644 apps/dokploy/pages/dashboard/home.tsx diff --git a/apps/dokploy/components/dashboard/home/show-home.tsx b/apps/dokploy/components/dashboard/home/show-home.tsx new file mode 100644 index 000000000..6e40d794a --- /dev/null +++ b/apps/dokploy/components/dashboard/home/show-home.tsx @@ -0,0 +1,223 @@ +import { formatDistanceToNow } from "date-fns"; +import { Plus, Rocket } from "lucide-react"; +import Link from "next/link"; +import { useMemo } from "react"; +import { Button } from "@/components/ui/button"; +import { api } from "@/utils/api"; + +type DeploymentStatus = "idle" | "running" | "done" | "error"; + +const statusDotClass: Record = { + done: "bg-muted-foreground/60", + running: "bg-amber-500", + error: "bg-red-500", + idle: "bg-muted-foreground/30", +}; + +function getServiceInfo(d: any) { + const app = d.application; + const comp = d.compose; + if (app?.environment?.project && app.environment) { + return { + name: app.name as string, + environment: app.environment.name as string, + projectName: app.environment.project.name as string, + href: `/dashboard/project/${app.environment.project.projectId}/environment/${app.environment.environmentId}/services/application/${app.applicationId}`, + }; + } + if (comp?.environment?.project && comp.environment) { + return { + name: comp.name as string, + environment: comp.environment.name as string, + projectName: comp.environment.project.name as string, + href: `/dashboard/project/${comp.environment.project.projectId}/environment/${comp.environment.environmentId}/services/compose/${comp.composeId}`, + }; + } + return null; +} + +function StatCard({ + label, + value, + delta, +}: { + label: string; + value: string; + delta?: string; +}) { + return ( +
+ + {label} + +
+ {value} + {delta && ( + + {delta} + + )} +
+
+ ); +} + +export const ShowHome = () => { + const { data: auth } = api.user.get.useQuery(); + const { data: projects } = api.project.all.useQuery(); + const { data: servers } = api.server.all.useQuery(); + const { data: permissions } = api.user.getPermissions.useQuery(); + const canReadDeployments = !!permissions?.deployment.read; + const { data: deployments } = api.deployment.allCentralized.useQuery( + undefined, + { + enabled: canReadDeployments, + refetchInterval: 10000, + }, + ); + + const firstName = auth?.user?.firstName?.trim(); + + const { totals, serverCount } = useMemo(() => { + let applications = 0; + let compose = 0; + let databases = 0; + const dbKeys = [ + "postgres", + "mysql", + "mariadb", + "mongo", + "redis", + "libsql", + ] as const; + for (const p of projects ?? []) { + for (const env of p.environments ?? []) { + applications += env.applications?.length ?? 0; + compose += env.compose?.length ?? 0; + for (const key of dbKeys) { + databases += (env as any)[key]?.length ?? 0; + } + } + } + return { + totals: { + projects: projects?.length ?? 0, + applications, + compose, + databases, + services: applications + compose + databases, + }, + serverCount: servers?.length ?? 0, + }; + }, [projects, servers]); + + const recentDeployments = useMemo(() => { + if (!deployments) return []; + return [...deployments] + .sort( + (a, b) => + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), + ) + .slice(0, 10); + }, [deployments]); + + return ( +
+
+
+

+ {firstName ? `Welcome back, ${firstName}` : "Welcome back"} +

+

+ {totals.services} services across {serverCount}{" "} + {serverCount === 1 ? "server" : "servers"} · {totals.projects}{" "} + {totals.projects === 1 ? "project" : "projects"} +

+
+ +
+ +
+ + + + +
+ +
+
+
+ +

Recent deployments

+
+ {canReadDeployments && ( + + view all → + + )} +
+ {!canReadDeployments ? ( +
+ You do not have permission to view deployments. +
+ ) : recentDeployments.length === 0 ? ( +
+ No deployments yet. +
+ ) : ( +
    + {recentDeployments.map((d) => { + const info = getServiceInfo(d); + if (!info) return null; + const status = (d.status ?? "idle") as DeploymentStatus; + return ( +
  • + + +
    + + {info.name} + + + {info.projectName} · {info.environment} + +
    + + {status} + + + {formatDistanceToNow(new Date(d.createdAt), { + addSuffix: true, + })} + + + logs → + + +
  • + ); + })} +
+ )} +
+
+ ); +}; diff --git a/apps/dokploy/components/dashboard/search-command.tsx b/apps/dokploy/components/dashboard/search-command.tsx index 9946a54a9..841728dc1 100644 --- a/apps/dokploy/components/dashboard/search-command.tsx +++ b/apps/dokploy/components/dashboard/search-command.tsx @@ -167,7 +167,7 @@ export const SearchCommand = () => {