Static Site Build

The accent build command generates a directory of static HTML, CSS, and assets that can be served by any web server or hosting provider. Static builds are free – no license key is required.

The accent build Command

accent build --output ./public --base-url https://example.com

Flags

FlagDescriptionDefault
--output / -oOutput directory for generated filesoutput
--base-urlBase URL for absolute links and sitemaps(none; falls back to site.url)
--config / -cPath to config file./config.yaml
--cleanRemove output directory before buildingfalse

The --base-url flag is important for production builds. It sets the base for absolute URLs in sitemaps, RSS feeds, and canonical links. Always set it to your production domain.

Output Directory Structure

A typical build produces the following:

public/
  index.html              # Home page
  about/
    index.html            # About page
  blog/
    index.html            # Blog listing (page 1)
    page/
      2/index.html        # Blog listing (page 2)
    my-first-post/
      index.html          # Blog post
  docs/
    index.html            # Docs index
    getting-started/
      index.html
  feed.xml                # RSS feed
  sitemap.xml             # XML sitemap
  robots.txt              # Robots configuration
  assets/                 # Theme CSS, JS, and images
    css/
      style.css
    js/
      main.js
  media/                  # Pre-processed media files
    blog/
      my-first-post/
        hero.webp
        hero-thumb.webp

Every page becomes an index.html inside a directory matching its URL path. This produces clean URLs without file extensions on any web server.

You may also see small *.md/index.html files (e.g. blog.md/index.html) next to the real pages. These are redirect stubs that bounce GitHub-style .md links to the clean URL; each is a meta-refresh with a canonical link, and they are excluded from sitemap.xml and feed.xml. To omit them, set content.md_extension_redirects: false in config.yaml.

Preview with serve-static

Before deploying, preview the build output locally using serve-static:

accent build --output ./public --base-url https://example.com
accent serve-static --dir ./public
# Visit http://127.0.0.1:4403

To preview over HTTPS (useful for testing service workers or mixed-content policies):

accent serve-static --dir ./public --tls
# Visit https://127.0.0.1:4403 (accept the self-signed certificate warning)

This is especially useful in CI pipelines for running smoke tests against the built output before deploying.

Deploy to Cloudflare Pages

Cloudflare Pages provides free hosting with a global CDN. Deploy with GitHub Actions:

# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install Accent CMS
        run: |
          curl -fsSL https://accentcms.dev/install.sh | sh
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Build site
        run: accent build --output ./public --base-url ${{ vars.SITE_URL }}

      - name: Deploy
        uses: cloudflare/wrangler-action@v3
        with:
          command: pages deploy ./public --project-name=my-site
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}

Set SITE_URL as a repository variable and CLOUDFLARE_API_TOKEN as a repository secret in your GitHub settings.

Deploy to Netlify

Create a netlify.toml in your project root:

[build]
  command = "accent build --output ./public --base-url https://example.com"
  publish = "public"

[build.environment]
  # Netlify will use this to install Accent CMS
  ACCENTCMS_VERSION = "latest"

[[redirects]]
  from = "/*"
  to = "/404.html"
  status = 404

Alternatively, deploy with the Netlify CLI:

accent build --output ./public --base-url https://your-site.netlify.app
npx netlify deploy --prod --dir=./public

Deploy to GitHub Pages

Use GitHub Actions to build and deploy to GitHub Pages:

# .github/workflows/pages.yml
name: Deploy to GitHub Pages

on:
  push:
    branches: [main]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install Accent CMS
        run: |
          curl -fsSL https://accentcms.dev/install.sh | sh
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Build site
        run: accent build --output ./public --base-url https://username.github.io/repo

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./public

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

Enable GitHub Pages in your repository settings under Settings > Pages and select GitHub Actions as the source.

Deploy to Vercel

Create a vercel.json in your project root:

{
  "buildCommand": "accent build --output ./public --base-url https://example.vercel.app",
  "outputDirectory": "public",
  "cleanUrls": true
}

Deploy with the Vercel CLI:

npx vercel --prod

Deploy to Any Web Server

Copy the public/ directory to the document root of any web server:

accent build --output ./public --base-url https://example.com

# Copy to a remote server
rsync -avz --delete ./public/ user@server:/var/www/example.com/

# Or serve locally with nginx
sudo cp -r ./public/* /var/www/html/

nginx Configuration for Static Files

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com;

    # Clean URLs: try directory index first
    location / {
        try_files $uri $uri/index.html =404;
    }

    # Cache static assets aggressively
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Custom 404 page
    error_page 404 /404.html;
}

Caddy Configuration

example.com {
    root * /var/www/example.com
    file_server
    try_files {path} {path}/index.html
}

Differences from Dynamic Serving

The static build output is functionally identical to what the dynamic server renders, with a few differences:

AspectDynamic ServerStatic Build
PaginationRendered on requestPhysical page/N/index.html files
PluginsExecute at request timeExecute once at build time
Media processingOn-demand (first request triggers processing)All media pre-processed at build time
Content updatesEdit file, refresh browserEdit file, rebuild, redeploy
Config changesSIGHUP to reload, or restartRebuild required
RSS/SitemapGenerated on requestGenerated as static files

Templates, markdown rendering, and page output are identical between the two modes.

CI/CD Pipeline Example

A complete GitHub Actions workflow that builds, tests, and deploys:

# .github/workflows/deploy.yml
name: Build and Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install Accent CMS
        run: |
          curl -fsSL https://accentcms.dev/install.sh | sh
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Validate content
        run: accent validate

      - name: Build site
        run: accent build --output ./public --base-url ${{ vars.SITE_URL }}

      - name: Check for broken links
        run: |
          npx broken-link-checker-local ./public --recursive

      - name: Deploy (main branch only)
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: |
          # Replace with your deployment command
          rsync -avz --delete ./public/ user@server:/var/www/site/

Pull requests run the build and validation steps without deploying, so you can catch issues before merging.

Next Steps