1
0
Fork 0

fix(deploy): set force-dynamic and outputFileTracingRoot for container builds

This commit is contained in:
Jason Fraley 2026-08-12 23:11:32 -04:00
parent 91c5a8f625
commit ba94dfa7da
3 changed files with 25 additions and 4 deletions

View file

@ -1,4 +1,6 @@
import { withPayload } from "@payloadcms/next/withPayload"; import { withPayload } from "@payloadcms/next/withPayload";
import path from "node:path";
import { fileURLToPath } from "node:url";
import packageJson from "./package.json" with { type: "json" }; import packageJson from "./package.json" with { type: "json" };
@ -8,6 +10,13 @@ const nextConfig = {
env: { env: {
version: packageJson.version, version: packageJson.version,
}, },
// Pin the workspace root to this repo dir so the standalone build emits a
// flat .next/standalone/server.js (Next otherwise walks up looking for
// lockfiles and can pick a parent directory — here a stray
// /home/jason/package-lock.json two levels up would nest the standalone
// tree under .next/standalone/WebstormProjects/polaris-task-force/, which
// breaks the Dockerfile's `COPY .../standalone ./` + `CMD ["node","server.js"]`).
outputFileTracingRoot: path.resolve(path.dirname(fileURLToPath(import.meta.url))),
webpack: (webpackConfig) => { webpack: (webpackConfig) => {
webpackConfig.resolve.extensionAlias = { webpackConfig.resolve.extensionAlias = {
".cjs": [".cts", ".cjs"], ".cjs": [".cts", ".cjs"],

View file

@ -15,6 +15,14 @@ import { GameTickRealtime } from "@/components/frontend/realtime/GameTickRealtim
import { LandingPage } from "@/components/frontend/LandingPage"; import { LandingPage } from "@/components/frontend/LandingPage";
import { Toaster } from "@/components/ui/sonner"; import { Toaster } from "@/components/ui/sonner";
// Skip static prerendering of this layout (and all pages under (frontend)/).
// The layout calls `getPayload()` at render time to resolve the current user,
// which connects to PostgreSQL. With force-dynamic, Next.js skips the
// build-time prerender pass (which would try to init Payload and hit the DB)
// and instead server-renders at request time. Without this, `next build`
// inside a container with no reachable DATABASE_URI fails.
export const dynamic = "force-dynamic";
export const metadata: Metadata = { export const metadata: Metadata = {
description: "A gamified platform for Polaris Task Force, an Arma 3 unit.", description: "A gamified platform for Polaris Task Force, an Arma 3 unit.",
title: "Polaris Task Force", title: "Polaris Task Force",

View file

@ -2,8 +2,13 @@ import { getPayload } from "payload";
import config from "@payload-config"; import config from "@payload-config";
import { headers as nextHeaders } from "next/headers"; import { headers as nextHeaders } from "next/headers";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
import { ShieldIcon } from "lucide-react";
import { LoginForm } from "@/components/frontend/auth/LoginForm"; import { LoginForm } from "@/components/frontend/auth/LoginForm";
import AppLogo from "@/components/graphics/AppLogo";
// See (frontend)/layout.tsx for rationale. The login page also calls
// getPayload() at render time and must not be prerendered during `next build`
// (no DB is available at build time in a container).
export const dynamic = "force-dynamic";
export default async function LoginPage() { export default async function LoginPage() {
const payload = await getPayload({ config }); const payload = await getPayload({ config });
@ -15,10 +20,9 @@ export default async function LoginPage() {
return ( return (
<div className="min-h-screen flex flex-col items-center justify-center p-5 gap-6 bg-background"> <div className="min-h-screen flex flex-col items-center justify-center p-5 gap-6 bg-background">
<div className="flex flex-col items-center gap-3 text-center max-w-md"> <div className="flex flex-col items-center gap-3 text-center max-w-md">
<div className="size-16 rounded-full border border-primary/40 bg-primary/10 flex items-center justify-center"> <div className="w-[260px] pb-2 [&_img]:w-full [&_img]:h-auto">
<ShieldIcon className="size-8 text-primary" /> <AppLogo />
</div> </div>
<h1 className="text-2xl font-semibold">Polaris Task Force</h1>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Log in to access the operations dashboard, intelligence, and Log in to access the operations dashboard, intelligence, and
logistics. logistics.