- Add .gitignore: exclude compiled binaries, build artifacts, and Helm values files containing real secrets (authentik, prometheus) - Add all Kubernetes deployment manifests (deployment/) - Add services source code: ha-sync, device-inventory, games-console, paperclip, parts-inventory - Add Ansible orchestration: playbooks, roles, inventory, cloud-init - Add hardware specs, execution plans, scripts, HOMELAB.md - Add skills/homelab/SKILL.md + skills/install.sh to preserve Copilot skill - Remove previously-tracked inventory-cli binary from git index Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
155 lines
4.2 KiB
Markdown
155 lines
4.2 KiB
Markdown
# 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 <id> # 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 <id> --quantity 180
|
|
parts delete <id> # prompts for confirmation
|
|
parts delete <id> --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<string, string\|number\|boolean>` | 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`
|