Single-binary self-hosted Markdown blog on Rust axum: no database, live search, Typst PDF export, and strong SEO.
axumblogdockermarkdownminijinjarustself-hostedtypstvite
1mod app;
2mod error;
3mod markdown;
4mod middleware;
5mod pdf;
6mod posts;
7mod render;
8mod routes;
9mod templates;
10
11use std::net::SocketAddr;
12
13#[tokio::main]
14async fn main() -> anyhow::Result<()> {
15 dotenvy::dotenv().ok();
16 tracing_subscriber::fmt()
17 .with_env_filter(
18 tracing_subscriber::EnvFilter::try_from_default_env()
19 .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
20 )
21 .init();
22
23 let port: u16 = std::env::var("PORT")
24 .ok()
25 .and_then(|v| v.parse().ok())
26 .unwrap_or(8000);
27
28 let state = app::AppState::from_env();
29 let router = app::router(state);
30
31 let addr = SocketAddr::from(([0, 0, 0, 0], port));
32 let listener = tokio::net::TcpListener::bind(addr).await?;
33 tracing::info!("blog listening on http://{addr}");
34 axum::serve(listener, router).await?;
35 Ok(())
36}