Arsenal IQ
Arsenal IQ is a self-hosted ERP-style inventory app for recording firearms and ammunition. It tracks serial numbers, acquisition cost, estimated value, ammunition on hand by caliber, and ammo cost, with a React frontend and a Docker Compose deployment model that supports both local development and Traefik-backed production.
Stack
- Frontend: React + TypeScript + Vite
- Backend: Node.js + Express + TypeScript
- Database: PostgreSQL 16
- Runtime: Docker Compose
- Proxy: optional Traefik production override
Features
- Firearm registry with manufacturer, model, serial number, caliber, category, storage location, and cost basis
- Ammunition lot tracking with caliber, grain, quantity on hand, vendor, cost per round, and reorder thresholds
- Dashboard summaries for inventory counts, invested value, and low-stock alerts
- Seed data so the UI is useful immediately after first startup
Quick start
- Copy the environment file.
cp .env.example .env
- Create the shared Traefik Docker network if you do not already have it.
docker network create traefik_proxy
- Build and start the local development stack.
docker compose up --build
Local endpoints
- Frontend:
http://localhost:3000 - API:
http://localhost:5000/api - Health check:
http://localhost:5000/health - PostgreSQL:
localhost:5432
Development storage
This project now uses local bind mounts instead of named Docker volumes:
- PostgreSQL data:
./data/postgres - Backend dependencies:
./backend/node_modules - Frontend dependencies:
./frontend/node_modules
On first start, the backend and frontend containers will install dependencies into those local node_modules folders before launching.
Production with Traefik
For production, use the dedicated production compose file so Traefik labels and external networking are only enabled there.
docker compose -f docker-compose.prod.yml up --build -d
Configure these values in .env for your production domain names:
TRAEFIK_NETWORK=traefik_proxy
TRAEFIK_ENTRYPOINT=websecure
TRAEFIK_WEB_HOST=arsenal.example.com
TRAEFIK_API_HOST=api.arsenal.example.com
If the frontend should call the API through Traefik in production, set:
VITE_API_BASE_URL=https://api.arsenal.example.com/api
FRONTEND_URL=https://arsenal.example.com
API routes
GET /healthGET /apiGET /api/dashboardGET /api/firearmsGET /api/ammo