Servable: a simple web framework
A minimal, convenient web micro-framework built around htmx, Axum, and Maud.
This powers my homepage. See example usage here.
Features
servable provides abstractions that implement common utilities needed by an http server.
- response headers and cache-busting utilities
- client device detection (mobile / desktop)
- server-side image optimization (see the
imagefeature below) - ergonomic htmx integration (see
htmx-*features below)
Quick Start
use ;
async
Core Concepts
The Servable trait
The Servable trait is the foundation of this stack.
servable provides implementations for a few common servables:
-
StaticAsset, for static files like CSS, JavaScript, images, or plain bytes:use ; let asset = StaticAsset ; -
Redirect, for simple http redirects:use Redirect; let redirect = new.unwrap; -
HtmlPage, for dynamically-rendered HTML pagesuse ; use html; use Pin; let page = default .with_meta .with_render;HtmlPageautomatically generates a<head>and wraps its rendered html in<html><body>.
ServableRouter
A ServableRouter exposes a collection of Servables under different routes. It implements tower's Service trait, and can be easily be converted into an Axum Router. Construct one as follows:
# use ;
# let home_page = StaticAsset ;
# let about_page = StaticAsset ;
# let stylesheet = StaticAsset ;
# let custom_404_page = StaticAsset ;
let route = new
.add_page
.add_page
.add_page
.with_404; // override default 404
Features
-
image: enable image transformation via query parameters. This makestokioa dependency.
When this is enabled, allStaticAssetswith a valid mimetype can take an optionalt=query parameter.
See theTransformerEnumin this crate's documentation for details.When
imageis enabled, the image below...# use ; let route = new .add_page;...may be accessed as follows:
# Original image GET /image.png # Resize to max 800px on longest side GET /image.png?t= # Crop to a 400x400 square at the center of the image GET /image.png?t= # Chain transformations and transcode GET /image.png?t=;; -
htmx-2.0.8: Include htmx sources in the compiled executable.
Use as follows:# use ServableRouter; # let route = new .add_page .add_page;
Caching and cache-busting
Control caching behavior per servable:
use TimeDelta;
use HtmlPage;
let page = default
.with_ttl
.with_private;
Headers are automatically generated:
Cache-Control: public, max-age=3600(default)Cache-Control: private, max-age=31536000(ifprivateis true)
We also provide a static CACHE_BUST_STR, which may be formatted into urls to force cache refresh
whenever the server is restarted:
use TimeDelta;
use ;
use MimeType;
pub static HTMX: = new;
let route = HTMX.route;
println!;
let router = new
.add_page_with_route;
TODO:
- cache-busting fonts in css is not possible, we need to dynamic replace urls