# Parts Inventory A self-hosted web app and CLI for organizing hardware: tools, screws, relays, electronics, and anything else with a label on it. Backed by MongoDB, deployed on Kubernetes. --- ## Features - **Flexible schema** — standard fields (title, type, category, manufacturer, dimensions, quantity, location, notes, tags) plus a free-form `properties` map for type-specific extras (e.g. thread pitch, coil voltage, resistance value) - **Fuzzy search** — MongoDB text index + Fuse.js re-ranking; finds "M3 hex screw" from "m3 hexscrew" - **Filter by type & category** — dropdown filters alongside search - **Web UI** — React + TypeScript, served by nginx; no login required (LAN access) - **REST API** — Node.js + Express + TypeScript - **CLI** — Go binary (`parts`) for quick terminal access --- ## Architecture ``` Browser ──► nginx (parts-ui :8080) ──► /api/* ──► parts-api (:3001) ──► MongoDB (:27017) ▲ parts-cli (Go) ``` --- ## Local Development ### API ```bash cd api npm install # needs a local MongoDB; start one with: # docker run -d -p 27017:27017 --name parts-mongo mongo:7 MONGO_URI=mongodb://localhost:27017/parts npm run dev ``` ### UI ```bash cd ui npm install # proxies /api to localhost:3001 (see vite.config.ts) npm run dev ``` ### CLI ```bash cd cli go mod download go run . list # or build: go build -o parts . ./parts --help ``` Default API URL: `http://localhost:3001`. Override with `PARTS_API_URL` env var or `~/.parts-inventory.yaml`: ```yaml api_url: http://parts.vandachevici.ro ``` --- ## CLI Usage ```bash parts list # list all parts parts list -q "m3 screw" # fuzzy search parts list -t screw -c fasteners # filter by type + category parts get # show full detail parts add --title "M3x10 hex screw" --type screw --category fasteners \ --quantity 200 --location "bin A3" \ --property thread=M3 --property length_mm=10 parts update --quantity 180 parts delete # prompts for confirmation parts delete --yes # skip prompt ``` --- ## Deploy to Kubernetes ### 1. Create the secret ```bash kubectl create secret generic parts-inventory-secret \ --from-literal=MONGO_URI="mongodb://parts-db.infrastructure.svc.cluster.local:27017/parts" \ -n infrastructure ``` ### 2. Build and load images ```bash cd /home/dan/homelab/services/parts-inventory ./build-and-load.sh ``` This builds `parts-api:latest`, `parts-ui:latest`, and `parts-cli:latest` and loads them onto kube-node-2 and kube-node-3 via `ctr`. ### 3. Apply the manifest ```bash kubectl apply -f /home/dan/homelab/deployment/infrastructure/parts-inventory.yaml ``` The UI will be available at **https://parts.vandachevici.ro** once the cert-manager TLS cert is issued. --- ## Schema | Field | Type | Notes | |-------|------|-------| | `title` | string | **Required**. Full-text indexed. | | `type` | string | e.g. `tool`, `screw`, `relay`, `sensor`, `cable` | | `category` | string | e.g. `fasteners`, `power tools`, `automation` | | `manufacturer` | string | Optional. Full-text indexed. | | `dimensions.width/length/height` | number | Optional. | | `dimensions.unit` | string | `mm`, `cm`, or `in` | | `quantity` | number | Default `1` | | `location` | string | e.g. `shelf A3, bin 2` | | `notes` | string | Full-text indexed. | | `tags` | string[] | Full-text indexed. | | `properties` | `Record` | Type-specific extras | ### Example `properties` ```json // Screw { "thread": "M3", "pitch_mm": 0.5, "head": "hex", "material": "stainless" } // Relay { "coil_voltage": 12, "contact_rating_A": 10, "form": "SPDT" } // Resistor { "value_ohm": 10000, "tolerance": "1%", "package": "0603" } ``` --- ## Project Structure ``` services/parts-inventory/ ├── api/ Node.js + Express + TypeScript REST API ├── ui/ React + TypeScript + Vite web app ├── cli/ Go + cobra CLI ├── build-and-load.sh └── PLAN.md ``` Manifest: `deployment/infrastructure/parts-inventory.yaml`