# Static Files _Path: en/http/static_ ## Table of Contents - Static Files ## Content # Static Files Serve static files from any filesystem using `http.static`. Static handlers mount directly on the server and can serve SPAs, assets, or user uploads from any path. ## Configuration ```yaml - name: static kind: http.static meta: server: gateway path: / fs: app:public directory: dist static_options: spa: true index: index.html cache: "public, max-age=3600" ``` | Field | Type | Description | |-------|------|-------------| | `meta.server` | Registry ID | Parent HTTP server | | `path` | string | URL mount path (must start with `/`) | | `fs` | Registry ID | Filesystem entry to serve from | | `directory` | string | Subdirectory within filesystem | | `static_options.spa` | bool | SPA mode - serve index for unmatched paths | | `static_options.index` | string | Index file (required when spa=true) | | `static_options.cache` | string | Cache-Control header value | | `middleware` | []string | Middleware chain | | `options` | map | Middleware options (dot notation) | Static handlers can be mounted to any path on the server. Multiple handlers can coexist—mount assets at /static and an SPA at /. ## Filesystem Integration Static files are served from filesystem entries. Any filesystem type works: ```yaml entries: # Local directory - name: public kind: fs.directory directory: ./public # Static handler - name: static kind: http.static meta: server: gateway path: /static fs: public ``` Request `/static/css/style.css` serves `./public/css/style.css`. The `directory` field selects a subdirectory within the filesystem: ```yaml - name: docs kind: http.static meta: server: gateway path: /docs fs: app:content directory: documentation/html ``` ## SPA Mode Single Page Applications need all routes to serve the same index file for client-side routing: ```yaml - name: spa kind: http.static meta: server: gateway path: / fs: app:frontend static_options: spa: true index: index.html ``` | Request | Response | |---------|----------| | `/app.js` | Serves `app.js` (file exists) | | `/users/123` | Serves `index.html` (SPA fallback) | | `/api/data` | Serves `index.html` (SPA fallback) | When spa: true, the index file is required. Existing files are served directly; all other paths return the index file. ## Cache Control Set appropriate caching for different asset types: ```yaml entries: - name: app_fs kind: fs.directory directory: ./dist # Versioned assets - cache forever - name: assets kind: http.static meta: server: gateway path: /assets fs: app_fs directory: assets static_options: cache: "public, max-age=31536000, immutable" # HTML - short cache, must revalidate - name: app kind: http.static meta: server: gateway path: / fs: app_fs static_options: spa: true index: index.html cache: "public, max-age=0, must-revalidate" ``` Common cache patterns: - **Versioned assets**: `public, max-age=31536000, immutable` - **HTML/index**: `public, max-age=0, must-revalidate` - **User uploads**: `private, max-age=3600` ## Middleware Apply middleware for compression, CORS, or other processing: ```yaml - name: static kind: http.static meta: server: gateway path: / fs: app:public middleware: - compress - cors options: compress.level: "best" cors.allow.origins: "*" ``` Middleware wraps the static handler in order—requests pass through each middleware before reaching the file server. Path matching is prefix-based. A handler at / catches all unmatched requests. Use routers for API endpoints to avoid conflicts. ## See Also - [Server](http/server.md) - HTTP server configuration - [Routing](http/router.md) - Routers and endpoints - [Filesystem](lua/storage/filesystem.md) - Filesystem module - [Middleware](http/middleware.md) - Available middleware ## Navigation Previous: Middleware (http/middleware) Next: WebSocket Relay (http/websocket-relay)