Skip to main content

Static assets

If you want to host static content, such as a web app that consumes your API, you can configure a staticFolder. This allows Temba to host your frontend assets alongside your API.

Configuring a staticFolder automatically sets the apiPrefix to "api". This is a strict requirement to ensure that API requests and page navigation remain separate.

To enable static content, add the folder name to your configuration. Usually, this is the folder where your build process outputs files, like dist or build.

const config = {
staticFolder: 'build',
}
const server = await create(config)

Notes

  • A physical index.html must exist in the staticFolder, otherwise a 404 is returned for any non-API request.
  • Only GET or HEAD requests are supported for static assets.

As further explained below, by default Temba tries to resolve each request URL to a physical file first and otherwise generally serves index.html. This is called "spa" mode.

If you want to only allow requests to actually existing files, and otherwise return a 404, use "filesystem" mode, by configuring staticFolder as an object:

const config = {
staticFolder: {
path: 'build',
mode: 'filesystem',
},
}
const server = await create(config)

For most projects, this is all you need to know about static content. If your application has complex routing or want to understand exactly how requests are handled, the details are below.


How it works

Request routing order

When you use a staticFolder, Temba processes every incoming request in a specific order of precedence. This ensures that your API works correctly and your static files are served efficiently.

  1. API prefix check
    If the request path starts with /api/, it is handled by the API. If the resource does not exist, Temba returns an API-flavored 404 error. Static files are never checked for these requests.

  2. Physical file check
    If the request is not for the API, Temba looks for a physical file in your staticFolder that matches the URL. If it finds one, it serves it.

  3. SPA fallback logic
    If no physical file exists, Temba determines if it should serve your index.html as a fallback. This happens only when:

  • The mode is set to "spa" (the default).
  • The Accept header includes text/html.
  • And either the last segment of the URL contains no dot (e.g., /dashboard), or it is a path that explicitly requests HTML despite having a dot (e.g., /user/john.doe).

Note: Requests for directories without a trailing slash (like /admin) will be automatically redirected to /admin/ if an index.html is found in that directory.

When these conditions are met, Temba searches for the nearest index.html by walking back through the URL path segments starting from the requested location.

  • Direct match It checks the requested directory for an index.html.
  • Walk back If not found, it moves up one directory level and checks again.
  • Root fallback This continues until it either finds an index.html or reaches the root of the staticFolder.
  1. 404 not found
    If none of the above conditions are met, the server returns a standard 404.

Single page application (SPA) support

Temba natively supports client-side routing using the History API. This means you can use libraries like React Router or Vue Router with "clean" URLs without the page breaking on a refresh.

By checking the Accept header and looking for dots in the URL, Temba intelligently decides when to send the user back to your index.html entry point and when to correctly report a missing asset.

Example scenarios

The following examples assume that the staticFolder is configured as 'build'.

requestresult
GET /serves build/index.html
GET /api/moviesAPI request for movies resource
GET /css/style.cssserves build/css/style.css (physical file check)
GET /dashboardno file found; serves build/index.html (SPA fallback)
GET /user/john.doebrowser asks for HTML; serves build/index.html
GET /missing-style.cssno file found; dot detected in last segment; returns 404