Skip to main content
If a static site has a _headers file in the repository’s root directory, Sevalla will parse the file’s contents and apply the custom header rules to matching responses.

Header rule format and examples

Each header rule starts with a path on its own line, followed by one or more indented header definitions in the format Header-Name: value. Any line beginning with # will be treated as a comment and ignored. Paths are case-sensitive. For example:
# Security headers for all pages
/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff

# Cache static assets for one year
/assets/*
  Cache-Control: public, max-age=31536000, immutable

# Custom header for the API
/api/*
  X-Api-Version: 2.0
Header rules are processed from top to bottom, and all matching rules are applied. If multiple rules match the same path, their headers are combined. When the same header name appears in multiple matching rules, the values are merged with a comma separator.

Applying headers to all pages

Use the /* wildcard pattern to set headers that apply across your entire site:
/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
This is useful for security headers, which typically need to be present on every response.

Wildcards

An asterisk (*) represents a wildcard, which matches any characters in a path, including slashes. For example:
/images/*
  Cache-Control: public, max-age=86400
This applies the Cache-Control header to any path under /images/, such as /images/logo.png or /images/icons/arrow.svg. You can also use wildcards within a path segment to match file extensions:
/*.css
  Cache-Control: public, max-age=31536000

/*.js
  Cache-Control: public, max-age=31536000
Note: Wildcards are greedy - /*.svg will match both /logo.svg and /images/icons/logo.svg, as the wildcard crosses directory boundaries.

Placeholders

You can use placeholders to match a single path segment. A placeholder starts with : followed by a name and matches any characters except /. For example:
/docs/:version/*
  X-Docs-Version: latest
In this example, the rule matches paths like /docs/v2/getting-started or /docs/v3/api-reference, but not /docs/ by itself.

Combining multiple rules

When multiple rules match a request path, all of their headers are applied to the response. If the same header name appears in more than one matching rule, the values are combined with a comma separator. For example:
/*
  Cache-Control: public
  X-Custom: global

/api/*
  Cache-Control: no-store
  X-Api: true
A request to /api/users matches both rules. The resulting headers would be:
  • Cache-Control: public, no-store
  • X-Custom: global
  • X-Api: true
To avoid conflicting cache directives, place more specific rules carefully and avoid overlapping Cache-Control values between wildcard and specific rules.

Common use cases

Security headers

/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  Permissions-Policy: camera=(), microphone=(), geolocation=()

Caching static assets

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

/*.html
  Cache-Control: public, max-age=0, must-revalidate

Custom headers for an API path

/api/*
  Access-Control-Allow-Origin: *
  X-Api-Version: 2.0

CORS for font files

/fonts/*
  Access-Control-Allow-Origin: *

Restricted headers

Certain headers are managed by the platform and cannot be overridden. If a restricted header appears in your _headers file, it will be silently ignored. The following headers are restricted:
  • Accept-Ranges
  • Age
  • Allow
  • Alt-Svc
  • Connection
  • Content-Encoding
  • Content-Length
  • Content-Range
  • Date
  • Location
  • Server
  • Trailer
  • Transfer-Encoding
  • Upgrade