diff --git a/Dockerfile b/Dockerfile index 5ab9e36..7eeb2ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,17 @@ -FROM nginx:alpine +FROM node:20-alpine -# Copy custom nginx config -COPY nginx.conf /etc/nginx/nginx.conf +WORKDIR /app -# Copy the static export to nginx html directory -COPY build /usr/share/nginx/html +# Next.js standalone runtime. Required because the contact form's Server +# Action (sendEmail.ts, SMTP via nodemailer) needs a live Node process - +# it cannot run under static/nginx serving. +ENV NODE_ENV=production +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 -EXPOSE 80 +# Copy the standalone build artifact (server.js, .next/, public/) +COPY build /app -CMD ["nginx", "-g", "daemon off;"] +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/build.sh b/build.sh index 9ddf254..46f85bb 100755 --- a/build.sh +++ b/build.sh @@ -1,31 +1,92 @@ #!/bin/bash -# Exit on error -set -e +# Deploy pipeline: doormile-next (Next.js standalone Node server) -> build/ -> Node Docker image. +# Standalone (not static export) is required because the contact form's Server +# Action (src/actions/sendEmail.ts, SMTP via nodemailer) needs a live Node +# process at runtime - it cannot run under static/nginx serving. +set -euo pipefail -# Change directory to the Next.js project -echo "🚀 Building Next.js application..." -cd ../doormile-next -npm install -npm run build +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOURCE_REPO="${SOURCE_REPO:-$SCRIPT_DIR/../doormile-next}" +DEPLOY_REPO="$SCRIPT_DIR" +STANDALONE_DIR="$SOURCE_REPO/.next/standalone" +BUILD_DIR="$DEPLOY_REPO/build" -# Go back to the build directory -echo "🧹 Preparing build context..." -cd ../doormile-build -rm -rf build -mkdir -p build +echo "Source repository: $SOURCE_REPO" +echo "Deploy repository: $DEPLOY_REPO" -# Copy Next.js standalone server and dependencies -echo "📦 Copying standalone build files..." -cp -R ../doormile-next/.next/standalone/. ./build/ +if [ ! -d "$SOURCE_REPO" ]; then + echo "ERROR: source repository not found at $SOURCE_REPO" >&2 + exit 1 +fi -# Copy public folder and static assets -echo "📦 Copying public and static assets..." -cp -R ../doormile-next/public ./build/ -mkdir -p ./build/.next -cp -R ../doormile-next/.next/static ./build/.next/ +if [ ! -f "$SOURCE_REPO/package.json" ] || [ ! -f "$SOURCE_REPO/next.config.ts" ]; then + echo "ERROR: $SOURCE_REPO does not look like the Next.js source repo (missing package.json or next.config.ts)" >&2 + exit 1 +fi -# Run the docker build -echo "🐳 Building Docker image..." -docker build -t doormile-app . +if ! grep -Eq 'output:\s*"standalone"' "$SOURCE_REPO/next.config.ts"; then + echo "ERROR: $SOURCE_REPO/next.config.ts does not have output: \"standalone\"." >&2 + echo "This pipeline runs the app as a Node server (required by the SMTP Server Action) - a non-standalone build cannot be deployed here." >&2 + exit 1 +fi -echo "✅ Docker build completed successfully!" +SOURCE_BRANCH="$(git -C "$SOURCE_REPO" branch --show-current)" +SOURCE_HEAD="$(git -C "$SOURCE_REPO" rev-parse HEAD)" +DEPLOY_BRANCH="$(git -C "$DEPLOY_REPO" branch --show-current)" +DEPLOY_HEAD_BEFORE="$(git -C "$DEPLOY_REPO" rev-parse HEAD)" + +echo "Source branch/HEAD: $SOURCE_BRANCH @ $SOURCE_HEAD" +echo "Deploy branch/HEAD (before sync): $DEPLOY_BRANCH @ $DEPLOY_HEAD_BEFORE" + +echo "Cleaning previous build artifacts in source repo (.next)..." +rm -rf "$SOURCE_REPO/.next" + +echo "Building Next.js application..." +(cd "$SOURCE_REPO" && npm run build) + +if [ ! -f "$STANDALONE_DIR/server.js" ]; then + echo "ERROR: $STANDALONE_DIR/server.js not found after build. Standalone output was not generated." >&2 + exit 1 +fi +echo "Standalone server verified at $STANDALONE_DIR/server.js" + +echo "Replacing deploy build/ with the fresh standalone artifact..." +rm -rf "$BUILD_DIR" +mkdir -p "$BUILD_DIR" + +# server.js, node_modules, package.json, and the traced .next/server tree +rsync -a "$STANDALONE_DIR"/ "$BUILD_DIR"/ +# static assets and public/ are deliberately excluded from standalone output +# by Next.js and must be copied manually +mkdir -p "$BUILD_DIR/.next" +rsync -a --delete "$SOURCE_REPO/.next/static"/ "$BUILD_DIR/.next/static"/ +rsync -a --delete "$SOURCE_REPO/public"/ "$BUILD_DIR/public"/ + +if [ ! -f "$BUILD_DIR/server.js" ] || [ ! -d "$BUILD_DIR/.next/static" ] || [ ! -d "$BUILD_DIR/public" ]; then + echo "ERROR: $BUILD_DIR is missing required standalone artifacts (server.js, .next/static, public)." >&2 + exit 1 +fi +echo "Artifact verified: build/server.js, build/.next/static, build/public all present." + +echo +echo "Source: $SOURCE_REPO ($SOURCE_BRANCH @ $SOURCE_HEAD)" +echo "Deploy: $DEPLOY_REPO ($DEPLOY_BRANCH @ $DEPLOY_HEAD_BEFORE)" +echo "Synced: $STANDALONE_DIR (+ .next/static, public) -> $BUILD_DIR" +echo +echo "Deploy repo status:" +git -C "$DEPLOY_REPO" status --short + +echo +if command -v docker >/dev/null 2>&1; then + echo "Building Docker image..." + (cd "$DEPLOY_REPO" && docker build -t doormile-app .) +else + echo "WARNING: docker not found on this machine - skipping 'docker build'." >&2 + echo "Run 'docker build -t doormile-app .' from $DEPLOY_REPO once docker is available." >&2 +fi + +echo +echo "Done. This script did NOT commit, push, or trigger Dokploy." +echo "Review the diff above, then: git add -A && git commit && git push, and redeploy doormilesite in Dokploy." +echo "Dokploy must route to internal container port 3000." +echo "Required SMTP environment variables in Dokploy: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, CONTACT_RECEIVER" diff --git a/build/404.html b/build/404.html deleted file mode 100644 index 0678dde..0000000 --- a/build/404.html +++ /dev/null @@ -1,680 +0,0 @@ -
=r)){let s=t[1];e=(r=t[--n-1]))break i}a=n,n=0;break r}break n}for(;n>>1;e