AssetForge — inventory without a database
AssetForge is a CSV-backed asset and custody tracker. The site is public and read-only by default. Admins sign in to add gear, move locations, attach photos and hand receipts, and — the part I cared about — paste CA-signed TLS certs into Settings so nginx reloads HTTPS without SSHing into the box.
Why it exists
I wanted tagged inventory that can run offline / air-gapped, does not require Postgres, and still behaves like a real small web app: dashboard, asset detail, checkout history, export. SaaS inventory tools are fine until you need it on a LAN with your own CA and no outbound CDN calls.
Access model
- Anyone — browse dashboard, assets, and locations (GET stays open)
- Admin — CRUD inventory, manage other admins, settings, CSV export, uploads
- First launch is a setup screen that creates the first administrator — no stock users
What an asset looks like
Tag, serial, manufacturer/model, status (AVAILABLE, CHECKED_OUT,
MAINTENANCE, RETIRED, LOST), condition, cost,
warranty, category, location, owner, assignee, optional photo and hand receipt.
Changing the assignee closes the open assignment and writes history — that is the
checkout story without a separate “loan” workflow.
Stack
- App — Next.js 15 (App Router), React 19, TypeScript, Tailwind
- Auth — JWT session cookie + bcrypt password hashes
- Storage — flat files under a data volume: assets / users / locations / categories / assignments / audit CSVs +
settings.json - TLS — nginx sidecar on 80/443; certs on a Docker volume hot-reloaded from Settings
- Fonts — vendored under
public/fonts(no Google Fonts at runtime)
CSV as the database
Writes use process-local locks and atomic rename. It is deliberately boring — easy to back up, easy to inspect, fine for personal / small-org inventory. Audit logs are capped so the file does not grow forever. This is not a multi-tenant SaaS store; it is a custody app you can ship as a compose stack.
HTTPS from Settings
Admins set a public FQDN, paste PEM certificate / key / optional CA chain, toggle force-HTTPS and secure cookies. The proxy watches the cert volume and reloads within a few seconds. First boot can mint a self-signed cert until a real CA cert lands. That loop — UI → volume → nginx reload — is the feature I kept circling back to while building it.
What’s working vs next
- Done: public browse, admin CRUD, CSV export, TLS UI, themes, air-gapped fonts, Docker compose
- Next: tighter alert delivery when SMTP is configured (overdue / warranty thresholds already exist)
- Next: richer reports and bulk import polish
- Next: optional read-only API tokens for other garage tools
Related programming work: FS Switch Console on the network side of the same shop.