A living almanac of seasons, soil, and the quiet knowledge that used to be common. Rust axum with minijinja and Vite.
agriculturealmanacaxumfolk-knowledgegardeningminijinjarustseasonalvite
1use axum::{
2 extract::{Query, State},
3 response::{Html, Json},
4 routing::get,
5 Router,
6};
7use chrono_tz::America::New_York;
8use serde::Deserialize;
9
10use crate::almanac::{self, Assembled};
11use crate::app::AppState;
12use crate::error::AppError;
13
14pub fn router() -> Router<AppState> {
15 Router::new()
16 .route("/", get(index))
17 .route("/api/content", get(api_content))
18}
19
20#[derive(Deserialize)]
21struct ContentQuery {
22 #[serde(default)]
23 season: Option<String>,
24}
25
26fn build(state: &AppState, season: Option<&str>) -> Assembled {
27 let now = chrono::Utc::now().with_timezone(&New_York);
28 almanac::assemble_content(now, &state.data, season)
29}
30
31async fn index(
32 State(state): State<AppState>,
33 Query(q): Query<ContentQuery>,
34) -> Result<Html<String>, AppError> {
35 let content = build(&state, q.season.as_deref());
36 let tmpl = state.env.get_template("index.html")?;
37 Ok(Html(tmpl.render(content)?))
38}
39
40async fn api_content(
41 State(state): State<AppState>,
42 Query(q): Query<ContentQuery>,
43) -> Result<Json<Assembled>, AppError> {
44 Ok(Json(build(&state, q.season.as_deref())))
45}