Skip to main content
This guide will help you deploy a static site to Zerops using the Static service. You’ll learn how to set up the service, configure routing, and deploy your application.

Prerequisites

  • A Zerops account (sign up if you don’t have one)
  • A project in Zerops (create one in the GUI if needed)
  • Static files to deploy (HTML, CSS, JS) or a framework that builds to static files

Step 1: Create Static Service

  1. Go to your project dashboard in Zerops
  2. Click Add new service
  3. Select Static as the service type
  4. Set a unique hostname (e.g., app, web, site)
  5. Configure scaling settings (optional)
  6. Click Create service

Step 2: Configure Your Application

Create a zerops.yaml file in your repository root.
If you have pre-built static files:
zerops.yaml
zerops:
  - setup: app
    run:
      base: static
That’s it! This minimal configuration:
  • Serves your static files
  • Handles SPA routing automatically
  • Uses sensible defaults
Deploy your files using zcli push from your project directory.

Step 3: Deploy

  1. Go to your service in Zerops GUI
  2. Click Connect to GitHub/GitLab
  3. Authorize and select your repository
  4. Choose the branch
  5. Enable Deploy on push for automatic deployments
  6. Click Deploy
Every push to your selected branch will trigger an automatic deployment.

Step 4: Set Up Public Access

  1. Navigate to your service in Zerops GUI
  2. Go to Public access & routing
  3. Click Add new routing rule
  4. Choose:
    • Zerops subdomain (e.g., myapp.zerops.app), or
    • Custom domain (requires DNS configuration)
  5. Save the routing rule
Your site is now live!

Common Examples

React Application

zerops.yaml
zerops:
  - setup: app
    build:
      base: nodejs@20
      buildCommands:
        - npm ci
        - npm run build
      deployFiles:
        - build/~
      cache: node_modules
    run:
      base: static

Vue Application with Custom Redirects

zerops.yaml
zerops:
  - setup: app
    build:
      base: nodejs@20
      buildCommands:
        - npm install
        - npm run build
      deployFiles:
        - dist/~
    run:
      base: static
      routing:
        redirects:
          # Redirect www to non-www
          - from: https://www.example.com/*
            to: https://example.com
            status: 301
            preservePath: true

Gatsby Site with SEO

zerops.yaml
zerops:
  - setup: app
    build:
      base: nodejs@20
      buildCommands:
        - npm install
        - npm run build
      deployFiles:
        - public/~
      cache:
        - node_modules
        - .cache
    run:
      base: static
      # Prerender.io token set as secret in Zerops GUI

Multi-Domain Landing Pages

zerops.yaml
zerops:
  - setup: app
    build:
      base: nodejs@20
      buildCommands:
        - npm install
        - npm run build
      deployFiles:
        - dist/~
    run:
      base: static
      routing:
        redirects:
          # Product promo domain
          - from: https://promo.example.com/*
            to: https://example.com/special-offer
            status: 302
          
          # Legacy domain
          - from: https://old-site.com/*
            to: https://example.com
            status: 301
            preservePath: true

Routing Patterns

Masked Redirects

Show content from one URL while keeping another URL in the browser:
routing:
  redirects:
    # URL stays /about, but shows content from /about-us
    - from: /about
      to: /about-us
No status code means it’s a masked redirect. Perfect for URL aliases.

Path Preservation

Maintain the path when redirecting:
routing:
  redirects:
    # /blog/post-1 → /articles/post-1
    - from: /blog/*
      to: /articles/
      preservePath: true
      status: 301
When using preservePath with wildcards, ensure the to path ends with / for proper concatenation.

Domain Redirects

routing:
  redirects:
    # Redirect old domain to new
    - from: https://old-domain.com/*
      to: https://new-domain.com
      status: 301
      preserveQuery: true
    
    # Redirect all subdomains
    - from: https://*.staging.com/*
      to: https://production.com
      status: 302

SEO Optimization

Enable Prerender.io for search engine visibility:
  1. Sign up for Prerender.io
  2. In Zerops GUI, add secret variable:
    • Name: PRERENDER_TOKEN
    • Value: Your Prerender.io token
  3. (Optional) Set custom host in zerops.yaml:
run:
  base: static
  envVariables:
    PRERENDER_HOST: custom.prerender.host
Prerender automatically detects crawlers from Google, Bing, social media platforms, and AI tools (ChatGPT, Perplexity, Claude).

Security Headers

Add security headers for production:
zerops:
  - setup: app
    run:
      base: static
      routing:
        headers:
          - for: "/"
            values:
              X-Frame-Options: "'DENY'"
              X-Content-Type-Options: "'nosniff' always"
              X-XSS-Protection: "'1; mode=block' always"
              # CSP with escaped quotes
              Content-Security-Policy: '"default-src ''self''" always'

Troubleshooting

The Static service handles this automatically. If you’re getting 404s:
  • Check that you have an index.html in your root
  • Verify your deployFiles path is correct
  • Make sure you haven’t overridden the default routing
Add CORS configuration:
routing:
  cors: "*"
Check:
  • Status code is required for absolute URLs
  • Path preservation needs trailing / in target
  • Exact matches take priority over wildcards
  • Review logs in Zerops GUI for errors
Verify your framework’s output directory matches deployFiles:
  • React: build/ (Create React App) or dist/ (Vite)
  • Vue: dist/
  • Angular: dist/<project-name>/
  • Next.js: .next/ (static export)
Remember to quote header values:
  • Correct: X-Frame-Options: "'DENY'"
  • Wrong: X-Frame-Options: DENY

Migration from Full Nginx

If you’re migrating from a full Nginx service:
  1. Review your current Nginx configuration
  2. Map Nginx directives to Static service YAML:
    • try_files → Built-in default behavior
    • rewriterouting.redirects
    • add_header for CORS → routing.cors
    • Other headers → routing.headers
  3. Test thoroughly in a development environment
  4. Deploy to production
If you need features not available in Static service, you can always switch back to full Nginx using the migration tool in the GUI.

Next Steps

Advanced Routing

Learn complex routing patterns

Framework Examples

See framework-specific guides

Custom Headers

Set up security headers

Environment Variables

Configure environment variables

Build docs developers (and LLMs) love