Website for critterscan
  • Rust 72.7%
  • CSS 25.7%
  • Dockerfile 1.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-28 13:40:44 +02:00
content Fix typos; Add AI statement; 2026-09-18 22:29:01 +02:00
docs/adr Fix image propotrions 2026-09-17 20:38:28 +02:00
firmware Fix typos; Add AI statement; 2026-09-18 22:29:01 +02:00
src Fix typos; Add AI statement; 2026-09-18 22:29:01 +02:00
static Fix image propotrions 2026-09-17 20:38:28 +02:00
.gitignore Fix typos; Add AI statement; 2026-09-18 22:29:01 +02:00
Caddyfile Add rust code (sloped) 2026-09-16 18:40:29 +02:00
Cargo.lock Add webflasher 2026-09-16 23:41:47 +02:00
Cargo.toml Add neofox emojis, improve mobile version; 2026-09-17 14:31:48 +02:00
docker-compose.yml Add rust code (sloped) 2026-09-16 18:40:29 +02:00
Dockerfile Add webflasher 2026-09-16 23:41:47 +02:00
README.md Add ToDo 2026-09-28 13:40:44 +02:00

Critterscan website

Server-rendered site for the Critter Scanner, an open-source ESP32 critter scanner: documentation, firmware downloads with checksums, an in-browser flasher, and a news/build log. Built in Rust (axum + maud), fronted by Caddy, deployed with Docker Compose.

It emits plain HTML with no third-party resources — no CDN, no web fonts, no trackers, no cookies. The one bit of client-side JavaScript is the optional in-browser firmware flasher on /flash, and it's progressive enhancement: the command-line method is always shown and needs no JS (ADR-0001).

Heads up: this code was written and reviewed but not compiled in the environment it was generated in (no Rust toolchain there). It's structured to build cleanly; run cargo build / docker compose build locally and fix any environment-specific issues before deploying.

Quick start (Docker)

docker compose up --build
# then open http://localhost

For production, set your domain so Caddy provisions HTTPS automatically:

cp .env.example .env      # edit SITE_ADDRESS and BASE_URL
SITE_ADDRESS=critterscan.example BASE_URL=https://critterscan.example \
  docker compose up --build -d

Local development (no Docker)

cargo run
# serves on http://localhost:8080, using ./content, ./firmware, ./static

Environment variables (all optional): BIND_ADDR (default 0.0.0.0:8080), CONTENT_DIR (content), FIRMWARE_DIR (firmware), STATIC_DIR (static), BASE_URL (http://localhost, used for RSS links), RUST_LOG (info).

Building

cargo build --release      # binary at target/release/critterscan-web
docker compose build

Commit the generated Cargo.lock for reproducible builds.

Project layout

src/
  main.rs        routes (incl. /flash), state, static/download serving, shutdown
  config.rs      site identity + external links (edit this)
  content.rs     markdown loading, front matter, sanitize, mtime cache
  firmware.rs    scan release dirs, checksums, signatures
  feed.rs        RSS 2.0 feed
  views.rs       maud HTML views (structure), incl. the flasher page
static/
  style.css      the whole design; hand-written, no framework
  emoji/         self-hosted neofox art (logo, mascot, flasher) — see emoji/README.md
  board/         front/back renders + STEP model — see board/README.md
  vendor/        vendored esp-web-tools (no CDN) — see vendor/README.md
content/
  docs/          documentation (markdown) — includes the merged flashing guide
  news/          dated posts (markdown)
  pages/         impressum.md, datenschutz.md
firmware/
  v<version>/    one folder per release + optional manifest.json (see firmware/README.md)
docs/adr/        architecture decision records (kept with the repo)
Dockerfile  docker-compose.yml  Caddyfile

Adding content

Docs and news are the same pipeline — drop a markdown file in and it appears on the next request, no rebuild. Front matter example (news):

---
title: My update
date: 2026-10-01
summary: One line shown in the list and RSS.
tags: announcement, hardware
---

Body in **markdown**. Tables, footnotes and strikethrough are enabled.

The slug drops a leading YYYY-MM-DD-. Docs work the same way in content/docs/ (a date isn't required).

Firmware & the browser flasher

Firmware releases live under firmware/v<version>/ — see firmware/README.md for the layout, checksums, and how to build the merged factory image + manifest.json the web flasher needs.

The /flash page uses esp-web-tools over Web Serial, vendored locally (v10.4.0, in static/vendor/esp-web-tools/) to honour the no-CDN rule — no setup needed. esp-web-tools itself handles the supported / unsupported / not-secure states, so browsers without Web Serial (Safari, stable Firefox) are shown a message pointing at the command-line method.

Browser support for the flasher: Chrome, Edge, and Opera on desktop over HTTPS (or localhost). To actually complete a flash you need a real merged factory image + manifest.json (see firmware/README.md); the sample release ships a placeholder, so the flow will prompt for a port but has nothing real to write until you add a build.

Customizing

  • Identity & links: src/config.rs — name, tagline, repo, social, donation URL, contact email.
  • Legal pages: content/pages/impressum.md and datenschutz.md (bracketed placeholders + a "not legal advice" note).
  • Design: everything visual is in static/style.css, driven by CSS custom properties (warm light + dark themes, neofox-orange accent) at the top. The logo, mascot, and flasher art are the neofox PNGs in static/emoji/.
  • Critter emoji (neofox): self-host with attribution — see static/emoji/README.md. The footer credit is required (CC BY-NC-SA 4.0).

What's intentionally stubbed (see docs/adr/)

  • Login (ADR-0007) — the "Log in" button leads to a placeholder page.
  • Interactive 3D viewer (ADR-0008) — evaluated and dropped; the front/back image gallery (front shown, back on demand) proved enough. Board images and the STEP download ship.
  • GPG signatures (ADR-0005) — the firmware page shows pending until the signing workflow exists; checksums ship now.

Client-side JS is limited to one sanctioned, progressive-enhancement exception (ADR-0001): the /flash browser flasher. The board front/back gallery is pure CSS.

License

Dual-licensed under MIT or Apache-2.0, at your option. Neofox emoji art (if added) is CC BY-NC-SA 4.0 by Volpeon and is not covered by this project's license.

ToDo

  • security scan/ hardening
  • include Firmware
  • signing