diff --git a/Dockerfile b/Dockerfile index 5473448..8f00060 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,10 @@ WORKDIR /app ENV NODE_ENV production ENV NEXT_TELEMETRY_DISABLED 1 +# Add the commit hash +ARG GIT_REV +ENV GIT_REV ${GIT_REV} + RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs diff --git a/next.config.mjs b/next.config.mjs index 4678774..90d4b78 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,23 @@ +import nextBuildId from "next-build-id"; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file +const __dirname = path.dirname(__filename); // get the name of the directory + /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + env: { + NEXT_PUBLIC_BUILD_ID: process.env.GIT_REV || nextBuildId.sync({ dir: __dirname }), + NEXT_PUBLIC_BUILD_TIME: new Date().toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + timeZoneName: "short", + }) + } +}; export default nextConfig; diff --git a/package.json b/package.json index 72fc260..0f04a74 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "ky": "^1.7.2", "lucide-react": "^0.440.0", "next": "14.2.11", + "next-build-id": "^3.0.0", "next-themes": "^0.3.0", "react": "^18", "react-chartjs-2": "^5.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8a9a66..0c840ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,6 +68,9 @@ dependencies: next: specifier: 14.2.11 version: 14.2.11(react-dom@18.3.1)(react@18.3.1) + next-build-id: + specifier: ^3.0.0 + version: 3.0.0 next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1)(react@18.3.1) @@ -2679,6 +2682,11 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /next-build-id@3.0.0: + resolution: {integrity: sha512-B3JCsL/9Z/wkmo3EySukQHCgx89Aw0i4LPi2MEhCboQBJ6wpkYTIu1z6hOYKuw/S1Wy8ZRqCEq0dVY/ST6jGqg==} + engines: {node: '>=8'} + dev: false + /next-themes@0.3.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==} peerDependencies: diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6680cf8..75bbb36 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -10,6 +10,7 @@ import { ThemeProvider } from "@/components/providers/theme-provider"; import { Toaster } from "@/components/ui/toaster"; import { TooltipProvider } from "@/components/ui/tooltip"; import "./globals.css"; +import Footer from "@/components/footer"; const siteFont = localFont({ src: "./fonts/JetBrainsMono-Regular.woff2", @@ -78,9 +79,12 @@ export default function RootLayout({ > -
+
- {children} +
+ {children} +
+
diff --git a/src/common/website-utils.ts b/src/common/website-utils.ts index e535b62..4611280 100644 --- a/src/common/website-utils.ts +++ b/src/common/website-utils.ts @@ -6,3 +6,26 @@ export function setPlayerIdCookie(playerId: string) { document.cookie = `playerId=${playerId}`; } + +/** + * Gets if we're in production + */ +export function isProduction() { + return process.env.NODE_ENV === "production"; +} + +/** + * Gets the build information + * + * @returns the build information + */ +export function getBuildInformation() { + const buildId = process.env.NEXT_PUBLIC_BUILD_ID + ? isProduction() + ? process.env.NEXT_PUBLIC_BUILD_ID.slice(0, 7) + : "dev" + : ""; + const buildTime = process.env.NEXT_PUBLIC_BUILD_TIME; + + return { buildId, buildTime }; +} diff --git a/src/components/footer.tsx b/src/components/footer.tsx new file mode 100644 index 0000000..b32f043 --- /dev/null +++ b/src/components/footer.tsx @@ -0,0 +1,40 @@ +import NavbarButton from "@/components/navbar/navbar-button"; +import Link from "next/link"; +import { getBuildInformation } from "@/common/website-utils"; + +type NavbarItem = { + name: string; + link: string; +}; + +const items: NavbarItem[] = [ + { + name: "Home", + link: "/", + }, + { + name: "Source", + link: "https://git.fascinated.cc/Fascinated/scoresaber-reloadedv3", + }, +]; + +export default function Footer() { + const { buildId, buildTime } = getBuildInformation(); + + return ( +
+

+ Build: {buildId} ({buildTime}) +

+
+ {items.map((item, index) => { + return ( + + {item.name} + + ); + })} +
+
+ ); +} diff --git a/src/components/navbar/navbar.tsx b/src/components/navbar/navbar.tsx index 9f820eb..57e17e0 100644 --- a/src/components/navbar/navbar.tsx +++ b/src/components/navbar/navbar.tsx @@ -34,8 +34,8 @@ const renderNavbarItem = (item: NavbarItem) => ( export default function Navbar() { return ( -
-
+
+
{/* Left-aligned items */}