UXDL Docs

Deployment

Docker multi-stage builds, Vercel deploy, and environment promotion.

Deployment paths for React applications — Vite SPAs via Docker, Next.js via Vercel or Docker.

Vite SPA — Docker

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
 
ARG VITE_API_URL
ARG VITE_COGNITO_CLIENT_ID
ENV VITE_API_URL=$VITE_API_URL
ENV VITE_COGNITO_CLIENT_ID=$VITE_COGNITO_CLIENT_ID
 
RUN pnpm build
 
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

Build with environment args:

bash
docker build \
  --build-arg VITE_API_URL=https://api.staging.company.com \
  --build-arg VITE_COGNITO_CLIENT_ID=xxx \
  -t web-app:staging .
bash
# Link project once
vercel link
 
# Preview deploy (automatic on PR)
vercel
 
# Production
vercel --prod

Set environment variables in the Vercel dashboard per environment (Preview, Production).

Next.js — Docker (self-hosted)

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
 
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]

Enable standalone output in next.config.ts:

typescript
const nextConfig = { output: "standalone" };
export default nextConfig;

Promotion flow

  1. Merge PR → CI builds and runs tests.
  2. Preview deploy to staging URL.
  3. Run smoke tests against staging.
  4. Code owner approves production promote.
  5. Deploy to production and verify health endpoint.