From 55b41f8627b3c55f8ee20348bfd043b028a43ce5 Mon Sep 17 00:00:00 2001 From: Dom Rettig Date: Wed, 29 Apr 2026 15:03:00 -0700 Subject: [PATCH 1/2] bundle client assests in dockerfile --- Dockerfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9ee88eaa..6807a10d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# This is a fairly-standard multi-stage Dockerfile. We build +# This is a fairly-standard multi-stage Dockerfile. We build # backend in a Node image, and then we copy the built files # (but not the devDependencies [like typescript, etc.] or the raw source # files) to final images that we'll actually run. This makes the final image a @@ -18,6 +18,13 @@ COPY ["server", "./"] FROM server_base AS build_backend RUN npm run build +FROM node:24.14.1-bullseye-slim AS build_client +WORKDIR /app +COPY ["client/package.json", "client/package-lock.json", "./"] +RUN npm ci +COPY ["client", "./"] +RUN npm run build + # make a shared layer that can be the base for worker and api images. FROM node:24.14.1-bullseye-slim AS backend_base WORKDIR /app @@ -39,6 +46,7 @@ ENV BUILD_ID=$BUILD_ID # Expose 8080 because the backend will run on this port absent a # process.env.PORT to the contrary. FROM backend_base AS build_server +COPY --from=build_client /app/build ./client-build EXPOSE 8080 CMD ["node", "bin/www.js"] From 9c68dc9878a81b6239e7b95262275019c8376bd7 Mon Sep 17 00:00:00 2001 From: Dom Rettig Date: Wed, 29 Apr 2026 15:04:19 -0700 Subject: [PATCH 2/2] add server.ts changes --- server/server.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/server.ts b/server/server.ts index 4c21d95f..7437a23a 100644 --- a/server/server.ts +++ b/server/server.ts @@ -1,3 +1,5 @@ +import path from 'path'; +import { fileURLToPath } from 'url'; import express from 'express'; import makeApiApp from './api.js'; @@ -50,5 +52,17 @@ export default async function makeWWWServer(deps: Dependencies) { app.use('/api/v1', apiApp); + const clientBuildPath = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + 'client-build', + ); + app.use(express.static(clientBuildPath)); + app.get('{*path}', (_req, res, next) => { + const indexPath = path.join(clientBuildPath, 'index.html'); + res.sendFile(indexPath, (err) => { + if (err) next(); + }); + }); + return { app, shutdown }; }