All apps · 0 apps
InventoryWare
Docker app from make-ware's Repository
Overview
Readme
View on GitHubInventory Ware
Inventory Ware is a self-hosted inventory management application designed to help you track your belongings through image-based labeling. You can identify and manage items using either human-provided labels or AI-powered image analysis.
Project Structure
inventory-ware/
├── webapp/ # Next.js frontend application
│ ├── app/ # Next.js 16+ app directory
│ ├── components/ # React components (shadcn/ui)
│ ├── lib/ # Utility functions
│ └── hooks/ # Custom React hooks
├── shared/ # Shared types, schemas, and utilities
│ ├── src/
│ │ ├── schemas/ # Zod validation schemas
│ │ ├── types/ # TypeScript type definitions
│ │ ├── utils/ # Utility functions
│ │ └── pocketbase/ # PocketBase client configuration
│ └── dist/ # Compiled JavaScript (generated)
├── pocketbase/ # PocketBase backend
│ ├── pocketbase* # PocketBase binary (auto-downloaded)
│ ├── pb_data/ # Database and files (auto-created)
│ └── pb_hooks/ # PocketBase JavaScript hooks
├── cli/ # `iw` command line interface
│ └── src/
│ ├── commands/ # item / container / image / auth commands
│ └── ... # config, auth store, output formatting
├── scripts/ # Setup and utility scripts
└── package.json # Monorepo configuration
Quick Start
Prerequisites
- Node.js 22+
- Yarn v4 (configured via packageManager)
Setup
Clone and install dependencies:
git clone <your-repo> cd inventory-ware yarn installSetup PocketBase:
yarn setupThis downloads and configures PocketBase for your platform automatically.
Start development servers:
yarn devThis starts both Next.js (port 3000) and PocketBase (port 8090) concurrently.
Create PocketBase admin account:
yarn pb:adminFollow the prompts to create your admin account, then visit http://localhost:8090/_/
Available Scripts
Root Level Commands
yarn setup- Download and setup PocketBase binaryyarn dev- Start both Next.js and PocketBase in development modeyarn build- Build the shared package and Next.js application for productionyarn lint- Run ESLint on all workspacesyarn lint:fix- Run ESLint with auto-fix on all workspacesyarn lint:app- Run ESLint on app workspace onlyyarn lint:shared- Run ESLint on shared workspace onlyyarn clean- Clean build artifacts and PocketBase datayarn install:all- Install all dependenciesyarn typegen- Generate TypeScript types from PocketBase schema
PocketBase Commands
yarn pb:dev- Start PocketBase in development mode (auto-restart)yarn pb:serve- Start PocketBase in production modeyarn pb:admin- Create/manage admin accounts
Next.js Commands
yarn lint:app- Run ESLint on Next.js app (recommended)yarn workspace webapp dev- Start Next.js dev server onlyyarn workspace webapp build- Build Next.js app
Shared Package Commands
yarn lint:shared- Run ESLint on shared package (recommended)yarn workspace shared build- Build shared TypeScript packageyarn workspace shared dev- Watch mode for shared packageyarn workspace shared typegen- Generate types from PocketBase schemayarn workspace shared migrate:generate- Generate database migrationyarn workspace shared migrate:status- Check migration status
CLI Commands (iw)
The cli workspace provides iw, which talks to PocketBase through the same
shared mutators the webapp uses.
yarn workspace @project/shared build # required first
yarn workspace @project/cli build
node cli/dist/cli.js --help
yarn workspace @project/cli test # run CLI tests
yarn workspace @project/cli bundle # standalone single-file build
Common usage:
iw login # cache a session token
iw item list --json | jq # list items, machine readable
iw item create --label Drill --functional Tools \
--specific "Power Tools" --type Drill
iw container items <id> # what's inside a container
iw image upload photo.jpg --analyze # upload + AI analysis
Released versions ship as a standalone build attached to each GitHub release,
and via brew install make-ware/tap/iw. See cli/README.md
for configuration, exit codes, and the full command reference.
Configuration
ESLint
The monorepo uses a centralized ESLint configuration (eslint.config.mjs) that:
- Supports TypeScript across all workspaces
- Provides React/Next.js specific rules for the app workspace
- Allows console usage in the shared workspace
- Handles browser and Node.js globals appropriately
Run linting commands:
yarn lint # Lint all workspaces
yarn lint:fix # Auto-fix issues across all workspaces
yarn lint:app # Lint only the Next.js app
yarn lint:shared # Lint only the shared package
PocketBase
- Admin UI: http://localhost:8090/_/
- API Base: http://localhost:8090/api/
- Data Directory:
./pocketbase/pb_data/ - Hooks Directory:
./pocketbase/pb_hooks/
AI Provider
Image analysis runs against OpenAI or Google Gemini. Set the API key for the one
you want in .env:
| Variable | Purpose |
|---|---|
OPENAI_API_KEY |
Use OpenAI. Default model gpt-5.4-2026-03-05. |
GEMINI_API_KEY |
Use Google Gemini. Default model gemini-3.5-flash. |
AI_PROVIDER |
openai or google. Only needed when both keys are set. |
AI_MODEL |
Override the model for the active provider. |
AI_BASE_URL |
Point at a compatible endpoint (proxy, Azure, local server). |
If exactly one key is present that provider is selected automatically. An
unusable AI_MODEL falls back to the provider default with a warning; with no
key configured the app runs normally but the AI routes return
503 AI_NOT_CONFIGURED. OPENAI_MODEL and OPENAI_BASE_URL remain supported
as legacy aliases.
Next.js
- Dev Server: http://localhost:3000
- Built with: App Router, TypeScript, Tailwind CSS, shadcn/ui
- Components: Pre-configured with shadcn/ui component library
Development Workflow
Backend Development:
- Modify database schema via PocketBase Admin UI
- Add custom logic in
./pocketbase/pb_hooks/main.pb.js - Use PocketBase's built-in auth, file storage, and real-time features
Frontend Development:
- Build React components in
./webapp/components/ - Create pages in
./webapp/app/ - Use mutators from
@project/sharedfor all PocketBase data operations - All PocketBase operations are client-side only (no SSR)
- Build React components in
Full-Stack Features:
- Authentication (built into PocketBase)
- File uploads and storage
- Real-time subscriptions
- Custom business logic via hooks
Tech Stack
Frontend (Next.js)
- Framework: Next.js 16+ with App Router
- Language: TypeScript
- Styling: Tailwind CSS v4
- Components: shadcn/ui (Radix UI primitives)
- Forms: React Hook Form + Zod validation
- Icons: Lucide React
Backend (PocketBase)
- Database: SQLite (built-in)
- Auth: Multi-provider authentication
- API: Auto-generated REST + Real-time
- Admin: Web-based admin dashboard
- Hooks: JavaScript/TypeScript custom logic
Development
- Package Manager: Yarn v4 with workspaces
- Monorepo: Yarn workspaces
- Linting: ESLint
- Concurrent: Run multiple services simultaneously
Connecting Frontend to Backend
Important: Use Mutators for All Data Operations
All PocketBase data operations should use mutators, not direct PocketBase SDK calls. Mutators provide:
- Type-safe data access
- Automatic validation
- Consistent error handling
- Built-in filtering, sorting, and expansion options
See the Shared Package README for mutator documentation.
Important: Client-Side Only (No SSR)
This project does NOT use Server-Side Rendering (SSR) for PocketBase data. All PocketBase operations are performed client-side only. This avoids security issues with shared SDK instances and simplifies the architecture.
See PB_SSR.md for detailed information about why SSR is not recommended.
Using the Shared Package
The monorepo includes a shared workspace with:
- Mutators: Type-safe data access classes (use these for all data operations)
- Schemas: Zod validation schemas
- Types: TypeScript type definitions
- Migrations: Database migration generation
// In your Next.js app - Use mutators for data operations
import { UserMutator } from '@project/shared';
import { pb } from '@/lib/pocketbase'; // Client-side PocketBase instance
// Create a mutator instance
const userMutator = new UserMutator(pb);
// Type-safe data operations
const user = await userMutator.getById('user-id');
const users = await userMutator.getList(1, 10);
const newUser = await userMutator.create({ email, password });
Database Migrations
The shared workspace can generate migrations for PocketBase schema changes:
# Generate a migration from schema changes
yarn workspace shared migrate:generate
# Check migration status
yarn workspace shared migrate:status
Adding New Features
Backend (PocketBase)
- Create collections via Admin UI
- Set up relations and validation rules
- Add custom hooks in
pb_hooks/main.pb.js
Frontend (Next.js)
- Create API functions in
lib/ - Build components in
components/ - Add pages in
app/
Deployment
PocketBase
- Deploy binary to your server
- Set environment variables for production
- Configure domain and SSL
Next.js
- Build:
yarn build - Deploy to your preferred platform
- Update API URLs for production
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Test locally with
yarn dev - Submit a pull request
License
MIT License - see LICENSE file for details
Happy coding!
Media gallery
1 / 5Install InventoryWare on Unraid in a few clicks.
Find InventoryWare in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Download Statistics
Related apps
Explore more like this
Explore allDetails
dastron/inventory-ware:latestRuntime arguments
- Web UI
http://[IP]:[PORT:80]/- Network
bridge- Shell
sh- Privileged
- false
Template configuration
Host port for the web app, PocketBase API and admin (proxied by nginx on container port 80).
- Target
- 80
- Default
- 8889
- Value
- 8889
Persistent storage: PocketBase database and uploaded images.
- Target
- /data
- Default
- /mnt/user/appdata/inventory-ware
- Value
- /mnt/user/appdata/inventory-ware
Email for the auto-created PocketBase superuser.
- Target
- POCKETBASE_ADMIN_EMAIL
- Default
- admin@example.com
- Value
- admin@example.com
Password for the auto-created PocketBase superuser. MUST be set to a strong value - leaving it blank skips superuser creation.
- Target
- POCKETBASE_ADMIN_PASSWORD
Set this to use OpenAI for AI labeling (default model gpt-5.4-2026-03-05). Get a key at https://platform.openai.com/api-keys. Leave blank if you are using Gemini instead, or to label items manually only.
- Target
- OPENAI_API_KEY
Set this to use Google Gemini for AI labeling instead of OpenAI (default model gemini-3.5-flash). Get a key at https://aistudio.google.com/apikey. Leave blank if you are using OpenAI, or to label items manually only.
- Target
- GEMINI_API_KEY
Optional. Which provider to use: openai or google (gemini is accepted for google). Only needed when BOTH API keys are set - with one key the provider is detected automatically, and with both OpenAI wins unless you set this.
- Target
- AI_PROVIDER
Optional. Override the model used for image analysis on the active provider. Must be vision-capable (multimodal) - text-only models cannot analyze photos. An unusable value falls back to the provider default with a warning in the log.
- Target
- AI_MODEL
Optional. Any compatible endpoint ending in /v1 - e.g. Together AI (https://api.together.xyz/v1), Groq, OpenRouter, Azure, a proxy, or a local server such as Ollama (http://YOUR-SERVER-IP:11434/v1). Leave blank to use the provider's own API. Also set AI Model to a vision-capable model that endpoint offers.
- Target
- AI_BASE_URL
Logging verbosity: error, warn, info, debug, verbose. Applies to every service in the container.
- Target
- LOG_LEVEL
- Default
- info
- Value
- info