HTTP Headers

How Boltdocs handles HTTP headers — the default security headers, custom headers via config, cache control, and per-platform examples for Vercel, Netlify, Cloudflare, and nginx.

HTTP headers control how browsers, CDNs, and crawlers treat your documentation site: what they may cache, how long, what security policies they enforce, and how they handle redirects. This guide covers the headers Boltdocs sends for you, how to add your own, and how to apply them on the platform you deploy to.


What Boltdocs sends by defaultLink

In production builds (and boltdocs preview), Boltdocs applies a baseline set of hardening headers to every response, based on OWASP recommendations:

HeaderValuePurpose
X-Content-Type-OptionsnosniffPrevents MIME type sniffing.
X-Frame-OptionsDENYBlocks the site from being embedded in iframes (anti-clickjacking).
X-XSS-Protection1; mode=blockLegacy XSS filtering for older browsers.
Referrer-Policystrict-origin-when-cross-originSends referrer info only for same-origin requests.
Permissions-Policycamera=(), microphone=(), geolocation=()Denies access to sensitive browser features.
Strict-Transport-Securitymax-age=31536000; includeSubDomains; preloadEnforces HTTPS for one year (HSTS).
Development builds are not hardened

The default security headers are applied only in production mode. During boltdocs dev they are omitted so local tooling and mixed content stay friction-free — your own custom headers (below) still apply in dev.

When security.enableCSP is enabled, a Content-Security-Policy header is added on top. See the CSP guide for the exact policy and how to customize it.


Configuring headers — securityLink

Add, override, or remove headers from boltdocs.config.ts with the security block:

boltdocs.config.ts
export default defineConfig({
  security: {
    // Headers sent on every request (dev and production).
    headers: {
      'X-Robots-Tag': 'index, follow',
      'X-Permitted-Cross-Domain-Policies': 'none',
    },
    // Override headers applied last, so they can replace defaults.
    customHeaders: {
      // Keep the built-in defaults but relax HSTS for local staging.
      'Strict-Transport-Security': 'max-age=31536000',
    },
  },
})

Merge orderLink

The final response headers are merged in this order (later wins):

  1. Built-in security headers (production only).
  2. The generated Content-Security-Policy, when enableCSP is on.
  3. security.headers.
  4. security.customHeaders — always applied last, so it can intentionally replace any default.

Removing a default headerLink

The most reliable way to drop a default header is to set it to an empty value with customHeaders. An empty value is sent as a zero-length header, which most platforms treat as "remove" at the edge:

boltdocs.config.ts
export default defineConfig({
  security: {
    customHeaders: {
      'X-XSS-Protection': '',
    },
  },
})
Headers are sent by the server, not embedded in HTML

Boltdocs is a static site generator: the headers above are applied by the dev/preview server and, in production, by your hosting platform. The built HTML files themselves do not carry headers — see below to wire them on your platform.


Applying headers on your platformLink

For production, configure headers on the platform that serves the built dist/ (or docs/ output) folder. Below are the standard configuration files for the most common hosts.

Vercel — vercel.jsonLink

vercel.json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
        { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains; preload" },
        { "key": "Content-Security-Policy", "value": "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'" }
      ]
    },
    {
      "source": "/assets/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
      ]
    }
  ]
}

Netlify — _headersLink

_headers
/*
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
  Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'

/assets/*
  Cache-Control: public, max-age=31536000, immutable

Cloudflare Pages — _headersLink

The same _headers file format works on Cloudflare Pages:

_headers
/*
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  Referrer-Policy: strict-origin-when-cross-origin
  Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

/assets/*
  Cache-Control: public, max-age=31536000, immutable

nginxLink

nginx.conf
server {
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "DENY" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'" always;

  location /assets/ {
    add_header Cache-Control "public, max-age=31536000, immutable";
  }
}

Cache-Control best practicesLink

Static documentation sites get most of their performance from caching. The golden rules:

  • HTML documents: no-cache (or a short max-age). You want readers to see the latest docs within minutes of a deploy, so let the browser revalidate: Cache-Control: public, max-age=0, must-revalidate.
  • Hashed assets (JS/CSS/fonts/images): immutable. Boltdocs emits content-hashed filenames, so Cache-Control: public, max-age=31536000, immutable is safe and makes repeat visits load instantly.
  • Sitemap/robots: short max-age (e.g. 3600) so search engines pick up new pages quickly.
ResourceCache-Control
*.htmlpublic, max-age=0, must-revalidate
/assets/* (hashed)public, max-age=31536000, immutable
/sitemap.xml, /robots.txtpublic, max-age=3600
og-image.webp and other static imagespublic, max-age=86400

Verifying headersLink

Check what your deployed site actually sends:

bash
# Production
curl -sI https://docs.example.com/ | grep -iE 'content-security|x-frame|strict-transport|cache-control'

# Local production build
pnpm build && pnpm preview

# Headers served by the preview server (defaults + config)
curl -sI http://localhost:4173/ | grep -iE 'content-security|x-frame|strict-transport'

For a full scorecard, run your production URL through securityheaders.com — it grades your security headers and points out missing ones.


Where nextLink

  • CSP — the Content-Security-Policy header in depth: default policy, customization, and pitfalls.
  • Cache & Environment — Boltdocs' internal disk caches and cache environment variables.
  • CI/CD & Deployment — wire header verification and boltdocs doctor into your deploy pipeline.
Last updated on October 18, 2026

Was this page helpful?