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
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 80Build with environment args:
docker build \
--build-arg VITE_API_URL=https://api.staging.company.com \
--build-arg VITE_COGNITO_CLIENT_ID=xxx \
-t web-app:staging .Next.js — Vercel (recommended)
# Link project once
vercel link
# Preview deploy (automatic on PR)
vercel
# Production
vercel --prodSet environment variables in the Vercel dashboard per environment (Preview, Production).
Next.js — Docker (self-hosted)
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:
const nextConfig = { output: "standalone" };
export default nextConfig;Promotion flow
- Merge PR → CI builds and runs tests.
- Preview deploy to staging URL.
- Run smoke tests against staging.
- Code owner approves production promote.
- Deploy to production and verify health endpoint.