Self-Hosted / Generic
Pageflare works with any static site regardless of host or build system. This guide covers the most common self-hosted patterns: Docker builds, generic CI/CD pipelines, Nginx/Apache post-build integration, and cron-based re-optimization.
Core Pattern
Section titled “Core Pattern”Every integration follows the same three-step pattern:
# 1. Build your static sitenpm run build # or hugo, jekyll build, eleventy, etc.
# 2. Optimize the outputpageflare dist/ --in-place --no-progress
# 3. Deployrsync -avz dist/ user@server:/var/www/html/Installing pageflare
Section titled “Installing pageflare”npm (global)
Section titled “npm (global)”npm install -g @pageflare/clicurl installer (Linux/macOS)
Section titled “curl installer (Linux/macOS)”curl -fsSL https://get.appz.dev/pageflare/install.sh | shVerify
Section titled “Verify”pageflare --versionDocker
Section titled “Docker”Single-stage Dockerfile
Section titled “Single-stage Dockerfile”FROM node:20-alpine AS build
WORKDIR /app
# Install dependenciesCOPY package*.json ./RUN npm ci
# Install pageflareRUN npm install -g @pageflare/cli
# Copy sourceCOPY . .
# Build the siteRUN npm run build
# Optimize the outputARG PAGEFLARE_LICENSEENV PAGEFLARE_LICENSE=${PAGEFLARE_LICENSE}RUN pageflare dist/ --in-place --no-progress
# Serve with NginxFROM nginx:alpineCOPY --from=build /app/dist /usr/share/nginx/htmlEXPOSE 80Build and run:
docker build --build-arg PAGEFLARE_LICENSE=your-license-key -t mysite .docker run -p 8080:80 mysiteMulti-stage Dockerfile (with separate builder and server stages)
Section titled “Multi-stage Dockerfile (with separate builder and server stages)”FROM node:20-alpine AS depsWORKDIR /appCOPY package*.json ./RUN npm ci
FROM node:20-alpine AS builderWORKDIR /appCOPY --from=deps /app/node_modules ./node_modulesCOPY . .RUN npm run build
FROM node:20-alpine AS optimizerWORKDIR /appCOPY --from=builder /app/dist ./distARG PAGEFLARE_LICENSEENV PAGEFLARE_LICENSE=${PAGEFLARE_LICENSE}RUN npm install -g @pageflare/cli && \ pageflare dist/ --in-place --no-progress
FROM nginx:alpine AS serverCOPY --from=optimizer /app/dist /usr/share/nginx/htmlEXPOSE 80Generic CI/CD Pipeline
Section titled “Generic CI/CD Pipeline”The pattern is the same for any CI provider. See the CI/CD guide for provider-specific YAML examples (GitHub Actions, GitLab CI).
Generic shell script
Section titled “Generic shell script”#!/usr/bin/env bashset -e
# Buildnpm cinpm run build
# Optimizepageflare dist/ --in-place --no-progress
# Deploy (example: rsync to a server)rsync -avz --delete dist/ deploy@myserver.example.com:/var/www/html/Environment variable for license
Section titled “Environment variable for license”export PAGEFLARE_LICENSE="your-license-key"Or store it in a .env file (never commit this):
PAGEFLARE_LICENSE=your-license-keyLoad it in your script:
set -a && source .env && set +apageflare dist/ --in-place --no-progressNginx Integration
Section titled “Nginx Integration”Pageflare runs at build time, not at runtime. Point Nginx at the already-optimized output directory:
server { listen 80; server_name example.com;
root /var/www/html; index index.html;
# Serve pre-compressed files if available gzip_static on; brotli_static on;
# Cache static assets aggressively location ~* \.(css|js|woff2|png|jpg|webp|avif|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; }
location / { try_files $uri $uri/ $uri.html =404; }}After running pageflare, reload Nginx:
pageflare /var/www/html --in-place --no-progressnginx -s reloadApache Integration
Section titled “Apache Integration”<VirtualHost *:80> ServerName example.com DocumentRoot /var/www/html
<Directory /var/www/html> Options -Indexes +FollowSymLinks AllowOverride All Require all granted </Directory>
# Cache static assets <FilesMatch "\.(css|js|woff2|png|jpg|webp|avif|svg)$"> Header set Cache-Control "public, max-age=31536000, immutable" </FilesMatch></VirtualHost>Cron-Based Re-Optimization
Section titled “Cron-Based Re-Optimization”For sites that regenerate on a schedule (e.g., data-driven static sites rebuilt nightly), set up a cron job:
# Run at 3 AM every day0 3 * * * deploy /home/deploy/scripts/rebuild-and-optimize.sh >> /var/log/pageflare.log 2>&1#!/usr/bin/env bashset -e
SITE_DIR="/var/www/mysite"BUILD_DIR="$HOME/build/mysite"
cd "$BUILD_DIR"
echo "[$(date -Is)] Starting rebuild"
# Pull latest contentgit pull --quiet
# Buildnpm run build
# OptimizePAGEFLARE_LICENSE="$(cat /etc/pageflare-license)" \ pageflare dist/ --in-place --no-progress --json > /tmp/pageflare-last-run.json
# Swap in the optimized buildrsync -avz --delete dist/ "$SITE_DIR/"
echo "[$(date -Is)] Done — $(jq '.summary.bytes_after' /tmp/pageflare-last-run.json) bytes deployed"Output Verification
Section titled “Output Verification”Use --json to capture a machine-readable report and verify the optimization ran correctly:
pageflare dist/ --in-place --json > /tmp/report.json
# Check for errorsERRORS=$(jq '.summary.errors' /tmp/report.json)if [ "$ERRORS" -gt 0 ]; then echo "pageflare reported $ERRORS errors" >&2 exit 1fi
echo "Optimized $(jq '.summary.optimized' /tmp/report.json) files"Configuration File
Section titled “Configuration File”Place pageflare.jsonc in the directory where you run the command, or pass it explicitly:
pageflare dist/ --in-place --config /etc/pageflare/pageflare.jsonc{ "minify_html": true, "minify_css": true, "minify_js": true, "js_defer": true, "lazy_images": true, "img_dimensions": true, "font_swap": true}See the Configuration reference for all available options.
Next Steps
Section titled “Next Steps”- CI/CD Integration — provider-specific YAML examples for GitHub Actions and GitLab CI.
- Configuration reference — full list of optimization options.
- License management — how to activate and manage your Pro license.