Guides

Assets & production

Serve static files with Fast-Twitch middleware and configure production assets.

Serve files with middleware

Fast-Twitch provides fast-twitch.middlewares.file/wrap-file. Use it around your routes to serve files from a configured directory. The upload/static example combines this middleware with Integrant and multipart handling.

(ns application.server
  (:require [fast-twitch.middlewares.file :as file]
            [fast-twitch.routing :as routing]))

(def app
  (-> (routing/routes routes not-found)
      (file/wrap-file "static" {:url-root "static"})))

A request to /static/css/app.css reads static/css/app.css. Keep the file root and URL root in your application's configuration rather than duplicating paths across handlers.

Read the file middleware API.

Compose response middleware

Use Fast-Twitch's content-type middleware to infer MIME types, default-charset middleware for text responses, not-modified middleware for conditional requests, and head middleware for HEAD responses. Each has its own reference page:

Build browser assets separately

A browser build tool such as Vite can write hashed JavaScript and CSS into a dedicated output directory. Configure wrap-file to serve that directory and use the build manifest when generating HTML. Keep browser assets and generated server output separate from ClojureScript source.

Learn from the working example

The public repository's 04-file-upload-static-integrant-bulma example demonstrates static files, multipart form parameters and an Integrant component graph. Follow its README to build and run the example.

File wrapper arguments and options

wrap-file accepts [handler root-path] or [handler root-path options]. file-request accepts the request and the same root/options and resolves to a file response or nil. File requests are GET/HEAD. A missing file continues to the wrapped handler.

Option Behavior in the pinned implementation
:url-root URL prefix stripped before resolving under root-path; use "static" for /static/...
:index-files? Default true; try index.html when a runtime reports a directory
:show-dotfiles? Default false; dotfile path segments are rejected unless enabled
:headers Additional response headers as map or header strings
:prefer-handler? When true, delegates directly to the handler; this implementation does not then retry file serving

Paths are percent-decoded; invalid escapes, upward .. segments and NUL bytes fail resolution. Do not infer a symlink security policy beyond the implementation's path checks. Node/Deno use filesystem metadata/read APIs; Bun uses Bun.file. Worker Fetch environments do not acquire a filesystem API through this wrapper; use their asset binding/export setup instead.

A file response supplies Content-Length and Last-Modified when available. Add content-type/charset and conditional middleware as needed. HEAD returns no body. File-info and cache-policy are separate wrappers, not implicit full asset pipelines.

Verify the behavior

Use the complete upload/static example and request /static/readme.txt with GET and HEAD. Request a missing file and inspect the app's 404 fallback. Add a stylesheet beneath the configured root, rebuild and request its URL. An existing file does not mean its MIME type or caching policy matches your intended behavior: inspect the wire headers too.

Versioned assets versus mutable content

A year-long immutable policy is appropriate for content-addressed asset filenames; it is inappropriate for a mutable URL that must reflect updates. The framework cache-policy wrapper memoizes header policies, not article bodies. Native response/body streams are resources: do not place a once-consumable body in a reusable response cache.

Complete Celld Fetch build · Complete workerd build · Middleware settings.

Source revision a4eb73f96836d034c7a24fe09dc7d51e4c581f64

Built with Fast-Twitch · Integrant · Datastar

Search documentation

Search pages and API symbols

Start hereWelcome to Fast-TwitchRing HTTP applications and configured native clients and transports in ClojureScript.Start hereGetting startedCompile and run your first Fast-Twitch server.Core conceptsRequest & responseUnderstand the maps at the center of a Fast-Twitch application.Core conceptsRoutingMatch URL patterns and compose handlers.Core conceptsMiddlewareWrap handlers with focused request and response behavior.GuidesHTML & IntegrantCompose a UI system with Integrant and render Hiccup.