InventoryWare

InventoryWare

Docker app from make-ware's Repository

Overview

Self-hosted inventory manager that catalogs your belongings from photos. Snap a picture and InventoryWare identifies the item with AI vision - or label it yourself - then organizes everything into containers you can search. Includes an `iw` CLI for scripted bulk imports. Runs as one container with one data path; AI labeling is optional and works with OpenAI or Google Gemini.

Inventory 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

  1. Clone and install dependencies:

    git clone <your-repo>
    cd inventory-ware
    yarn install
    
  2. Setup PocketBase:

    yarn setup
    

    This downloads and configures PocketBase for your platform automatically.

  3. Start development servers:

    yarn dev
    

    This starts both Next.js (port 3000) and PocketBase (port 8090) concurrently.

  4. Create PocketBase admin account:

    yarn pb:admin
    

    Follow the prompts to create your admin account, then visit http://localhost:8090/_/

Available Scripts

Root Level Commands

  • yarn setup - Download and setup PocketBase binary
  • yarn dev - Start both Next.js and PocketBase in development mode
  • yarn build - Build the shared package and Next.js application for production
  • yarn lint - Run ESLint on all workspaces
  • yarn lint:fix - Run ESLint with auto-fix on all workspaces
  • yarn lint:app - Run ESLint on app workspace only
  • yarn lint:shared - Run ESLint on shared workspace only
  • yarn clean - Clean build artifacts and PocketBase data
  • yarn install:all - Install all dependencies
  • yarn 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 mode
  • yarn 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 only
  • yarn 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 package
  • yarn workspace shared dev - Watch mode for shared package
  • yarn workspace shared typegen - Generate types from PocketBase schema
  • yarn workspace shared migrate:generate - Generate database migration
  • yarn 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

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

  1. 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
  2. Frontend Development:

    • Build React components in ./webapp/components/
    • Create pages in ./webapp/app/
    • Use mutators from @project/shared for all PocketBase data operations
    • All PocketBase operations are client-side only (no SSR)
  3. 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)

  1. Create collections via Admin UI
  2. Set up relations and validation rules
  3. Add custom hooks in pb_hooks/main.pb.js

Frontend (Next.js)

  1. Create API functions in lib/
  2. Build components in components/
  3. 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

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Test locally with yarn dev
  5. Submit a pull request

License

MIT License - see LICENSE file for details


Happy coding!

Media gallery

1 / 5

Install 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.

Open the Apps tab on your Unraid server Search Community Apps for InventoryWare Review the template variables and paths Click Install

Download Statistics

494
Total Downloads

Details

Repository
dastron/inventory-ware:latest
Last Updated2026-08-17
First Seen2026-08-17

Runtime arguments

Web UI
http://[IP]:[PORT:80]/
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Host port for the web app, PocketBase API and admin (proxied by nginx on container port 80).

Target
80
Default
8889
Value
8889
App DataPathrw

Persistent storage: PocketBase database and uploaded images.

Target
/data
Default
/mnt/user/appdata/inventory-ware
Value
/mnt/user/appdata/inventory-ware
Admin EmailVariable

Email for the auto-created PocketBase superuser.

Target
POCKETBASE_ADMIN_EMAIL
Default
admin@example.com
Value
admin@example.com
Admin PasswordVariable

Password for the auto-created PocketBase superuser. MUST be set to a strong value - leaving it blank skips superuser creation.

Target
POCKETBASE_ADMIN_PASSWORD
OpenAI API KeyVariable

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
Gemini API KeyVariable

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
AI ProviderVariable

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
AI ModelVariable

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
AI Base URLVariable

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
Log LevelVariable

Logging verbosity: error, warn, info, debug, verbose. Applies to every service in the container.

Target
LOG_LEVEL
Default
info
Value
info