Any .js file in the routes directory that exports an HTTP method function will be treated as a handler.

This includes both virtual files and API routes.

Virtual Files

You can use a handler to expose what appears to be a static file that is actually generated on the fly.

import getOrRefreshSitemap from '../scripts/sitemap.js' export async function get(ctx) { const sitemap = await getOrRefreshSitemap() return new Response(sitemap, { headers: { 'Content-Type': 'application/xml', }, }) }

In this example, a sitemap is generated, cached and updated over time when the /sitemap.xml url is requested.

API Routes

You can handle multiple HTTP methods to form API routes.

Supported function names are get, put, patch, post, del and options.

export async function get(ctx) { const { id } = ctx.req.params return await ctx.db('users').where({ id }).first() } export async function put(ctx) { const data = await ctx.req.json() /* update and return user */ }

IMPORTANT: Unless your app needs to provide a public API to its users, we recommend building your entire app using Loaders and Actions instead of API routes due to how efficient they can be.


Handlers are provided a Context object that provides access to the Web API Request and utilities for managing cookies, route params and extras you've provided in your firebolt.config.js, such as database access.


Handlers can return any valid JSON and Firebolt will automatically respond with a Content-Type: application/json header and 200 status.

For more fine grained control, you can return a Web API Response instance, allowing you to set different headers, statuses and body types.