Skip to main content
CDN

Static files

How build output is deployed as versioned static assets and served without compute.

Files produced during your build are deployed as versioned static assets and served through Easel without invoking application compute.

Static files are well suited for JavaScript bundles, stylesheets, images, fonts, generated HTML, and files from your project’s public directory.

How static files are deployed

During a deployment, Easel identifies the files produced by your framework or build command and publishes them with that deployment.

Examples include:

  • JavaScript and CSS bundles
  • images and fonts
  • source maps
  • files from public, static, or equivalent directories
  • prerendered HTML
  • framework-generated client assets
  • downloadable files

Requests for these files are served directly and do not invoke an Easel Function.

Deployment versioning

Static files belong to a specific deployment.

A preview deployment and a production deployment can contain different versions of the same path without overwriting one another.

For example:

Preview deployment:
  /assets/app.js → preview build

Production deployment:
  /assets/app.js → production build

Promoting or publishing a new deployment updates which deployment serves the production domain. Existing immutable deployment URLs continue to reference their original files.

This allows Easel to switch deployments without partially updating a site.

Content-hashed assets

Modern frameworks commonly include a content hash in generated filenames:

/assets/app.9f3ac21.js
/assets/styles.701ad8c.css
/_next/static/chunks/4728.abf0981.js

When the file contents change, the filename changes as well.

These files can safely use long cache lifetimes because an updated deployment references a new URL instead of replacing the existing asset at the same path.

A typical policy is:

Cache-Control: public, max-age=31536000, immutable

Framework-generated assets may receive this policy automatically.

Stable URLs

Some files retain the same path when their contents change:

/index.html
/robots.txt
/manifest.webmanifest
/logo.svg

These files should generally use shorter cache lifetimes or require revalidation so visitors can receive updated versions after a deployment.

For example:

Cache-Control: public, max-age=0, must-revalidate

Avoid applying a one-year immutable policy to a stable URL unless the file is guaranteed never to change.

Static HTML

Pages generated during the build can be served as static HTML without invoking a function.

This includes:

  • prerendered framework routes
  • statically generated pages
  • HTML produced by a static-site generator
  • plain HTML files in the output directory

Static HTML and client assets may use different caching policies.

A framework can give HTML a short or revalidated lifetime while assigning long immutable lifetimes to hashed JavaScript and CSS files.

Output directories

Easel detects the conventional output directory for supported frameworks.

Common examples include:

Build tool or frameworkTypical output
Vitedist
Astrodist
static exportframework-defined export directory
plain static siteconfigured project directory

For full-stack frameworks, the static output may be only one part of the deployment. Easel can deploy static assets alongside server-rendered routes and functions.

You can override the build command, project root, or output configuration in the project settings when automatic detection is not appropriate.

Public directories

Files placed in a framework’s public directory are generally copied into the deployment output without changing their names.

Examples include:

public/favicon.ico        → /favicon.ico
public/robots.txt         → /robots.txt
public/images/logo.svg    → /images/logo.svg

Because these URLs do not usually contain content hashes, choose their cache policies carefully.

Custom response headers

You can configure headers for static files through supported framework configuration or Easel routing configuration.

For example, a content-hashed asset can use:

Cache-Control: public, max-age=31536000, immutable

A stable configuration file might use:

Cache-Control: public, max-age=300

A file that must always be checked for updates can use:

Cache-Control: public, max-age=0, must-revalidate

Custom headers should not weaken the cache safety of framework-generated assets unless you have a specific reason to override the defaults.

CDN behavior

Static files are served through the Easel CDN.

A request may be served from an existing cached copy or retrieved from the deployment’s asset storage and then cached for later requests.

The response can expose the cache result:

X-Easel-Cache: HIT

Serving a static file does not invoke an application function, regardless of whether the CDN reports HIT or MISS.

A cache miss for a static file means Easel had to retrieve the deployment asset. It does not mean the application was executed.

Compression

Eligible static files are compressed automatically when the visitor supports Brotli or gzip.

Common compressible files include:

  • HTML
  • CSS
  • JavaScript
  • JSON
  • SVG
  • XML
  • text files
  • WebAssembly

Already compressed formats such as JPEG, PNG, WebP, AVIF, ZIP, and most video files are generally sent without additional compression.

See Compression.

Content types

Easel determines the response Content-Type from the file extension and deployment metadata.

Examples include:

Content-Type: text/html; charset=utf-8
Content-Type: text/css; charset=utf-8
Content-Type: application/javascript; charset=utf-8
Content-Type: image/svg+xml
Content-Type: font/woff2

Use the correct file extension whenever possible.

A missing or incorrect content type can affect browser rendering, compression, and security behavior.

Range requests

Range requests bypass shared CDN caching.

Partial content (206) for deployment static assets is not currently supported. Clients that send a Range header for those assets should not expect a successful partial-content response from Easel’s CDN path.

Single-page applications

Client-rendered single-page applications often need unknown routes to return the application’s HTML entry point.

For example:

/dashboard/settings

may need to serve:

/index.html

Configure an SPA fallback through supported routing or framework configuration.

The fallback should apply only to application routes. Requests for missing assets such as /assets/missing.js should still return 404.

See the Vite guide.

Custom error pages

Static deployments can provide custom error documents where supported.

Common examples include:

404.html
500.html

The exact convention depends on the framework and routing configuration.

A custom error page can remain a static asset even when it is displayed for a failed route.

Preview and production deployments

Preview and production deployments use separate deployment versions.

This means:

  • preview assets do not overwrite production assets
  • the same path can contain different files in different deployments
  • promoting a deployment changes the production version as a unit
  • rollback can restore a previous deployment and its assets

Do not use a preview deployment URL as a permanent production asset origin. Preview deployments may be deleted or access-controlled independently from production.

Asset URLs

Prefer root-relative URLs for files served from the same deployment:

<img src="/images/logo.svg" alt="Easel">

Framework build tools usually rewrite asset references automatically.

When deploying beneath a path prefix or using an external asset host, configure the framework’s base path or asset prefix accordingly.

Examples include:

  • Vite base
  • Next.js basePath and assetPrefix
  • Nuxt app.baseURL
  • framework-specific public path configuration

See the relevant framework guide.

Missing files

A request for a file that does not exist in the selected deployment returns 404 unless a routing rule or SPA fallback matches it.

Check:

  • the build output contains the file
  • the filename uses the correct capitalization
  • the public path is correct
  • the project root is configured correctly
  • the output directory is correct
  • the asset URL includes the expected base path
  • the deployment being requested is the intended one

File paths are case-sensitive.

For example:

/images/Logo.svg

and:

/images/logo.svg

are different paths.

Large files

Static files remain subject to project and platform limits.

For large downloads, video, backups, or user-uploaded content, use object storage rather than including the files in every application deployment.

Application deployments are best suited for assets that are:

  • generated or versioned with the application
  • required by the application interface
  • reasonably sized
  • updated through normal deployments

User-generated files should generally be stored separately from deployment assets.

Deployment assets and object storage

Deployment assets are immutable files associated with an application release.

Object storage is intended for data that changes independently from application deployments.

Deployment assetsObject storage
Created during the buildCreated or updated at runtime
Versioned with a deploymentManaged independently
Read-only after deploymentCan support writes and deletes
Best for application filesBest for uploads and durable content
Released through a deployUpdated through application logic or APIs

Do not write user data to the deployment filesystem or a function’s local filesystem.

Debugging static files

Inspect the response headers:

curl -I https://example.com/assets/app.js

Useful headers include:

Content-Type: application/javascript; charset=utf-8
Cache-Control: public, max-age=31536000, immutable
Content-Encoding: br
X-Easel-Cache: HIT

A file returns 404

Verify that:

  • it exists in the build output
  • the output directory is configured correctly
  • the URL uses the correct capitalization
  • the framework base path matches the deployed URL
  • a rewrite is not sending the request elsewhere

A file has the wrong content type

Check the extension and whether a custom header rule overrides Content-Type.

Avoid serving JavaScript or CSS through extensionless URLs unless the response type is explicitly configured.

Visitors receive an old file

Check whether the file uses a stable URL with a long browser cache lifetime.

For files that change, use content-hashed filenames or shorter browser caching.

Purging Easel’s CDN cache does not remove a file already stored in a visitor’s browser.

An asset request invokes a function

Check whether:

  • a broad rewrite captures the asset path
  • an SPA fallback also matches files
  • the framework routes the path dynamically
  • the file is absent from the static build output

Exclude asset directories from broad rewrites and middleware matchers where appropriate.