Skip to content

feat: Enhance Next.js build process for static export compatibility #51

feat: Enhance Next.js build process for static export compatibility

feat: Enhance Next.js build process for static export compatibility #51

# Sample workflow for building and deploying a Next.js site to GitHub Pages
#
# To get started with Next.js see: https://nextjs.org/docs/getting-started
#
name: Deploy Next.js site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Build job
build:
runs-on: ubuntu-latest
env:
DEPLOY_TARGET: github-pages
NODE_ENV: production
# Add GitHub secrets as environment variables
GHOST_URL: ${{ secrets.GHOST_URL }}
GHOST_CONTENT_API_KEY: ${{ secrets.GHOST_CONTENT_API_KEY }}
SITE_URL: https://gerardo.js.org
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect package manager
id: detect-package-manager
run: |
if [ -f "${{ github.workspace }}/yarn.lock" ]; then
echo "manager=yarn" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=yarn" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then
echo "manager=pnpm" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=pnpm" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/package.json" ]; then
echo "manager=npm" >> $GITHUB_OUTPUT
echo "command=ci" >> $GITHUB_OUTPUT
echo "runner=npx --no-install" >> $GITHUB_OUTPUT
exit 0
else
echo "Unable to determine package manager"
exit 1
fi
- name: Setup pnpm
if: steps.detect-package-manager.outputs.manager == 'pnpm'
run: npm install -g pnpm
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: ${{ steps.detect-package-manager.outputs.manager }}
- name: Configure GitHub Pages
run: |
echo "Configuring for GitHub Pages deployment"
echo "Site URL: $SITE_URL"
echo "Deploy Target: $DEPLOY_TARGET"
- name: Restore cache
uses: actions/cache@v4
with:
path: |
.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
- name: Disable Next.js telemetry
run: npx next telemetry disable
- name: Clear Next.js cache
run: |
echo "🧹 Clearing Next.js cache..."
rm -rf .next
echo "βœ… Cache cleared"
- name: πŸ”§ Auto-fix Static Export Incompatibilities
run: |
echo "πŸš€ Starting static export compatibility fixes..."
# Remove known dynamic files that conflict with static export
echo "πŸ—‘οΈ Removing known dynamic files..."
rm -f app/robots.ts app/sitemap.ts
rm -rf app/api/fallback-icon
# Remove any API routes (not supported in static export)
if [ -d "app/api" ]; then
echo "πŸ—‘οΈ Removing remaining API routes..."
rm -rf app/api
fi
# Remove all files containing Server Actions (not supported in static export)
echo "πŸ” Finding files with Server Actions (excluding node_modules)..."
SERVER_ACTION_FILES=$(grep -r -l "use server" --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" --exclude-dir=node_modules . 2>/dev/null || true)
if [ -n "$SERVER_ACTION_FILES" ]; then
echo "πŸ“‹ Files to be removed:"
echo "$SERVER_ACTION_FILES"
echo "πŸ—‘οΈ Removing Server Action files..."
echo "$SERVER_ACTION_FILES" | xargs rm -f
echo "βœ… Server Action files removed successfully"
# Remove imports and usages from deleted Server Action files
echo "πŸ”§ Cleaning up imports and usages from deleted Server Action files..."
for deleted_file in $SERVER_ACTION_FILES; do
# Extract the module path (e.g., @/lib/actions from ./lib/actions.js)
module_path=$(echo "$deleted_file" | sed 's|^\./||' | sed 's|\.js$||' | sed 's|\.jsx$||' | sed 's|\.ts$||' | sed 's|\.tsx$||' | sed 's|^|@/|')
echo " Cleaning references to: $module_path"
# Find files that import from this module
grep -r -l "from.*$module_path" --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" --exclude-dir=node_modules . 2>/dev/null | while read file; do
echo " Cleaning imports in: $file"
# Remove import lines that reference this module
sed -i "/import.*from.*$(echo "$module_path" | sed 's|/|\\/|g')/d" "$file"
# Remove any remaining lines that use imported functions
sed -i '/analyzeWebsite/d' "$file"
# Remove any "use server" directives that might be left
sed -i '/^[[:space:]]*"use server"[[:space:]]*;*[[:space:]]*$/d' "$file"
done
done
echo "βœ… Import and usage cleanup completed"
else
echo "βœ… No Server Action files found"
fi
# Set dynamicParams to false for static export
echo "πŸ” Finding files with dynamicParams = true (excluding node_modules)..."
DYNAMIC_PARAMS_FILES=$(grep -r -l "dynamicParams.*=.*true" --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" --exclude-dir=node_modules . 2>/dev/null || true)
if [ -n "$DYNAMIC_PARAMS_FILES" ]; then
echo "πŸ“‹ Files with dynamicParams to be modified:"
echo "$DYNAMIC_PARAMS_FILES"
echo "πŸ”§ Setting dynamicParams to false for static export..."
echo "$DYNAMIC_PARAMS_FILES" | xargs sed -i 's/export const dynamicParams = true;/export const dynamicParams = false;/g'
echo "βœ… dynamicParams updated successfully"
else
echo "βœ… No dynamicParams files found"
fi
- name: Build with Next.js for GitHub Pages
run: |
echo "πŸ” Debug: Environment variables during build"
echo "DEPLOY_TARGET: $DEPLOY_TARGET"
echo "NODE_ENV: $NODE_ENV"
echo "GHOST_URL: $GHOST_URL"
echo "GHOST_CONTENT_API_KEY present: $(if [ -n "$GHOST_CONTENT_API_KEY" ]; then echo 'yes'; else echo 'no'; fi)"
echo "SITE_URL: $SITE_URL"
echo ""
echo "πŸš€ Starting Next.js build..."
${{ steps.detect-package-manager.outputs.runner }} run build
- name: Verify build output
run: |
echo "πŸ” Checking build output..."
echo "Current directory contents:"
ls -la ./
echo ""
echo "Next.js configuration that was used:"
if [ -f "next.config.js" ]; then
echo "Found next.config.js:"
cat next.config.js
fi
if [ -f "next.config.mjs" ]; then
echo "Found next.config.mjs:"
cat next.config.mjs
fi
echo ""
if [ -d "./out" ]; then
echo "βœ… out directory exists"
echo "Contents of out directory:"
ls -la ./out
echo ""
echo "Sample files in out directory:"
find ./out -type f -name "*.html" | head -5
else
echo "❌ out directory does not exist"
echo ""
echo "Checking .next directory:"
if [ -d "./.next" ]; then
echo ".next directory contents:"
ls -la ./.next
echo ""
echo "Checking .next/standalone:"
if [ -d "./.next/standalone" ]; then
ls -la ./.next/standalone
fi
else
echo ".next directory also does not exist"
fi
echo ""
echo "This suggests the static export is not working. Check next.config.mjs configuration."
exit 1
fi
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./out
# Deployment job
deploy:
environment:
name: github-pages
url: https://gerardo.js.org
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4