Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ lerna-debug.log*
# misc
.DS_Store
notes.mdx

# We dont need generated Prisma files
prisma/generated/
8 changes: 8 additions & 0 deletions apps/client/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# API Configuration
# NOTE: These are build-time variables for Vite
# They are baked into the static files during build
# To change them, rebuild the Docker image with --build-arg

VITE_API_URL=http://localhost:9999
VITE_APP_URL=http://localhost:80
VITE_BETTER_AUTH_URL=http://localhost:9999/api/auth
57 changes: 57 additions & 0 deletions apps/client/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# TanStack Start (SSR) Client Dockerfile
# Multi-stage build for optimized production image
#
# NOTE: This Dockerfile expects to be run from the monorepo root
# Build command: docker build -f apps/client/Dockerfile .

FROM oven/bun:latest AS base
WORKDIR /usr/src/app

# Install OpenSSL (required for some dependencies)
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*

# ============================================
# Build Stage
# ============================================
FROM base AS builder
WORKDIR /usr/src/app

# Copy root workspace files
COPY package.json bun.lock* ./

# Copy the entire monorepo structure (client needs server types)
COPY apps/server ./apps/server/
COPY apps/client ./apps/client/

# Install all dependencies from monorepo root
RUN bun install --frozen-lockfile
Comment thread
catalinpit marked this conversation as resolved.

# Set build-time environment variables (can be overridden during build)
ARG VITE_API_URL
ARG VITE_APP_URL
ARG VITE_BETTER_AUTH_URL

ENV VITE_API_URL=${VITE_API_URL}
ENV VITE_APP_URL=${VITE_APP_URL}
ENV VITE_BETTER_AUTH_URL=${VITE_BETTER_AUTH_URL}

Comment on lines +29 to +37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Provide defaults for VITE_ build ARGs to avoid empty config in builds*

Right now the ARG values default to empty, so running docker build ... (or bun run docker:build:client) without explicit --build-arg flags will bake empty VITE_API_URL, VITE_APP_URL, and VITE_BETTER_AUTH_URL into the client build.

You can make the image usable out of the box by giving these ARGs sane defaults that match .env.example, while still allowing overrides:

-# Set build-time environment variables (can be overridden during build)
-ARG VITE_API_URL
-ARG VITE_APP_URL
-ARG VITE_BETTER_AUTH_URL
-
-ENV VITE_API_URL=${VITE_API_URL}
-ENV VITE_APP_URL=${VITE_APP_URL}
-ENV VITE_BETTER_AUTH_URL=${VITE_BETTER_AUTH_URL}
+# Set build-time environment variables (can be overridden during build)
+ARG VITE_API_URL=http://localhost:9999
+ARG VITE_APP_URL=http://localhost:80
+ARG VITE_BETTER_AUTH_URL=http://localhost:9999/api/auth
+
+ENV VITE_API_URL=${VITE_API_URL}
+ENV VITE_APP_URL=${VITE_APP_URL}
+ENV VITE_BETTER_AUTH_URL=${VITE_BETTER_AUTH_URL}

This matches the documented defaults and reduces surprises when building locally.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Set build-time environment variables (can be overridden during build)
ARG VITE_API_URL
ARG VITE_APP_URL
ARG VITE_BETTER_AUTH_URL
ENV VITE_API_URL=${VITE_API_URL}
ENV VITE_APP_URL=${VITE_APP_URL}
ENV VITE_BETTER_AUTH_URL=${VITE_BETTER_AUTH_URL}
# Set build-time environment variables (can be overridden during build)
ARG VITE_API_URL=http://localhost:9999
ARG VITE_APP_URL=http://localhost:80
ARG VITE_BETTER_AUTH_URL=http://localhost:9999/api/auth
ENV VITE_API_URL=${VITE_API_URL}
ENV VITE_APP_URL=${VITE_APP_URL}
ENV VITE_BETTER_AUTH_URL=${VITE_BETTER_AUTH_URL}
🤖 Prompt for AI Agents
In apps/client/Dockerfile around lines 29–37, the ARGs VITE_API_URL,
VITE_APP_URL and VITE_BETTER_AUTH_URL are declared without defaults so builds
without --build-arg produce empty baked-in values; update each ARG declaration
to include the sensible default values from .env.example (for example the
documented local/dev defaults) so the ENV lines continue to pick up those ARGs
while still allowing overrides via --build-arg.

# Build the client application
WORKDIR /usr/src/app/apps/client
RUN bun run build

# ============================================
# Production Stage - Nginx
# ============================================
FROM nginx:alpine AS runner

# Copy built static files to nginx html directory
COPY --from=builder /usr/src/app/apps/client/dist/client /usr/share/nginx/html

# Copy custom nginx configuration
COPY apps/client/nginx.conf /etc/nginx/conf.d/default.conf

# Expose port 80
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]
35 changes: 35 additions & 0 deletions apps/client/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;

# Enable gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}

# SPA fallback - send all requests to index.html
location / {
try_files $uri $uri/ /index.html;
}

# Health check endpoint
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"packages/*"
],
"scripts": {
"clean": "rm -rf node_modules && rm -rf apps/*/node_modules && rm -rf packages/*/node_modules"
"clean": "rm -rf node_modules && rm -rf apps/*/node_modules && rm -rf packages/*/node_modules",
"docker:build:client": "docker build -f apps/client/Dockerfile -t learn-platform-client ."
}
}
}