diff --git a/apps/dokploy/components/dashboard/projects/show.tsx b/apps/dokploy/components/dashboard/projects/show.tsx
index 783c5bb32..5369a544e 100644
--- a/apps/dokploy/components/dashboard/projects/show.tsx
+++ b/apps/dokploy/components/dashboard/projects/show.tsx
@@ -14,6 +14,7 @@ import { useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
import { DateTooltip } from "@/components/shared/date-tooltip";
+import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input";
import { StatusTooltip } from "@/components/shared/status-tooltip";
import {
AlertDialog,
@@ -44,7 +45,6 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
-import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input";
import {
Select,
SelectContent,
@@ -52,12 +52,14 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
+import { TimeBadge } from "@/components/ui/time-badge";
import { api } from "@/utils/api";
import { HandleProject } from "./handle-project";
import { ProjectEnvironment } from "./project-environment";
export const ShowProjects = () => {
const utils = api.useUtils();
+ const { data: isCloud } = api.settings.isCloud.useQuery();
const { data, isLoading } = api.project.all.useQuery();
const { data: auth } = api.user.get.useQuery();
const { mutateAsync } = api.project.remove.useMutation();
@@ -135,6 +137,11 @@ export const ShowProjects = () => {
+ {!isCloud && (
+
+
+
+ )}
@@ -148,7 +155,6 @@ export const ShowProjects = () => {
Create and manage your projects
-
{(auth?.role === "owner" || auth?.canCreateProjects) && (
@@ -298,7 +304,13 @@ export const ShowProjects = () => {
{domain.host}
@@ -340,7 +352,13 @@ export const ShowProjects = () => {
{domain.host}
diff --git a/apps/dokploy/components/layouts/side.tsx b/apps/dokploy/components/layouts/side.tsx
index 8d84e260c..7473fe586 100644
--- a/apps/dokploy/components/layouts/side.tsx
+++ b/apps/dokploy/components/layouts/side.tsx
@@ -83,6 +83,7 @@ import { AddOrganization } from "../dashboard/organization/handle-organization";
import { DialogAction } from "../shared/dialog-action";
import { Logo } from "../shared/logo";
import { Button } from "../ui/button";
+import { TimeBadge } from "../ui/time-badge";
import { UpdateServerButton } from "./update-server";
import { UserNav } from "./user-nav";
@@ -1125,6 +1126,7 @@ export default function Page({ children }: Props) {
+ {!isCloud &&
}
)}
diff --git a/apps/dokploy/components/ui/time-badge.tsx b/apps/dokploy/components/ui/time-badge.tsx
new file mode 100644
index 000000000..ea7f1f84e
--- /dev/null
+++ b/apps/dokploy/components/ui/time-badge.tsx
@@ -0,0 +1,58 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import { api } from "@/utils/api";
+
+export function TimeBadge() {
+ const { data: serverTime } = api.server.getServerTime.useQuery(undefined);
+ const [time, setTime] = useState(null);
+
+ useEffect(() => {
+ if (serverTime?.time) {
+ setTime(new Date(serverTime.time));
+ }
+ }, [serverTime]);
+
+ useEffect(() => {
+ const timer = setInterval(() => {
+ setTime((prevTime) => {
+ if (!prevTime) return null;
+ const newTime = new Date(prevTime.getTime() + 1000);
+ return newTime;
+ });
+ }, 1000);
+
+ return () => {
+ clearInterval(timer);
+ };
+ }, []);
+
+ if (!time || !serverTime?.timezone) {
+ return null;
+ }
+
+ const getUtcOffset = (timeZone: string) => {
+ const date = new Date();
+ const utcDate = new Date(date.toLocaleString("en-US", { timeZone: "UTC" }));
+ const tzDate = new Date(date.toLocaleString("en-US", { timeZone }));
+ const offset = (tzDate.getTime() - utcDate.getTime()) / (1000 * 60 * 60);
+ const sign = offset >= 0 ? "+" : "-";
+ const hours = Math.floor(Math.abs(offset));
+ const minutes = (Math.abs(offset) * 60) % 60;
+ return `UTC${sign}${hours.toString().padStart(2, "0")}:${minutes
+ .toString()
+ .padStart(2, "0")}`;
+ };
+
+ return (
+
+ Server Time:
+
+ {time.toLocaleTimeString()}
+
+
+ ({serverTime.timezone} | {getUtcOffset(serverTime.timezone)})
+
+
+ );
+}
diff --git a/apps/dokploy/server/api/routers/server.ts b/apps/dokploy/server/api/routers/server.ts
index d6904a7ec..8a01228f8 100644
--- a/apps/dokploy/server/api/routers/server.ts
+++ b/apps/dokploy/server/api/routers/server.ts
@@ -383,6 +383,15 @@ export const serverRouter = createTRPCRouter({
const ip = await getPublicIpWithFallback();
return ip;
}),
+ getServerTime: protectedProcedure.query(() => {
+ if (IS_CLOUD) {
+ return null;
+ }
+ return {
+ time: new Date(),
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
+ };
+ }),
getServerMetrics: protectedProcedure
.input(
z.object({