Barcode-based inventory management system built with SvelteKit (frontend), FastAPI (backend), and PostgreSQL (database).
- π± Mobile-friendly barcode scanning using device camera
- π Automatic product lookup via Open Food Facts API
- π¦ Inventory tracking with location hierarchy (Schrank/Fach/Box)
- ββ Quick inventory adjustments
- ποΈ Local product database with caching
- π³ Complete Docker Compose setup
- FastAPI - Modern async Python web framework
- SQLAlchemy 2.0 - Async ORM with asyncpg driver
- Alembic - Database migrations
- PostgreSQL 15 - Database
- httpx - Async HTTP client for provider APIs
- SvelteKit - Modern Svelte framework with TypeScript
- @zxing/browser - Barcode scanning library
- Vite - Build tool and dev server
- Docker Compose - Container orchestration
- nginx - Reverse proxy for API and frontend
- Docker and Docker Compose
- (Optional) Node.js 20+ and Python 3.11+ for local development
-
Clone the repository
cd /root/metallschrank -
Configure environment
cp .env.example .env # Edit .env if needed (defaults work for local development) -
Start all services
docker compose up --build
This will:
- Start PostgreSQL database
- Run database migrations automatically
- Start FastAPI backend on port 8000
- Start SvelteKit frontend on port 5173
- Start nginx reverse proxy on port 80
-
Access the application
- Main app: http://localhost
- API docs: http://localhost/docs
- Direct backend: http://localhost:8000 (dev only)
- Direct frontend: http://localhost:5173 (dev only)
/root/metallschrank/
βββ backend/ # FastAPI application
β βββ app/
β β βββ api/ # API routes (lookup, products, inventory)
β β βββ core/ # Config, database setup
β β βββ models/ # SQLAlchemy models
β β βββ providers/ # Barcode lookup providers
β β βββ schemas/ # Pydantic schemas
β βββ alembic/ # Database migrations
β βββ tests/ # pytest tests
β βββ Dockerfile
β βββ requirements.txt
βββ frontend/ # SvelteKit application
β βββ src/
β β βββ lib/ # Components and utilities
β β β βββ components/ # Svelte components
β β β βββ api.ts # API client
β β βββ routes/ # SvelteKit pages
β β βββ scan/ # Barcode scanning page
β β βββ inventory/ # Inventory list page
β βββ Dockerfile
β βββ package.json
βββ infra/ # Infrastructure configs
β βββ nginx.conf # Reverse proxy config
β βββ init.sql # PostgreSQL init script
βββ docker-compose.yml # Container orchestration
βββ .env.example # Environment template
-
Install dependencies
cd backend source /path/to/venv/bin/activate pip install -r requirements.txt -r requirements-dev.txt
-
Create database migration
cd backend alembic revision --autogenerate -m "Description"
-
Apply migrations
alembic upgrade head
-
Run tests
pytest
-
Install dependencies
cd frontend npm install -
Run dev server
npm run dev
-
Build for production
npm run build
-
Lint and format
npm run lint npm run format
-
Create provider class in
backend/app/providers/your_provider.py:from app.providers.base import BaseProvider, ProviderResult class YourProvider(BaseProvider): @property def provider_name(self) -> str: return "your_provider" async def lookup(self, code: str) -> Optional[ProviderResult]: # Implement API call and normalization pass
-
Register in
backend/app/providers/__init__.py:from app.providers.your_provider import YourProvider provider_registry.register(YourProvider())
-
Enable in
.env:BARCODE_PROVIDERS=openfoodfacts,your_provider
POST /api/lookup- Lookup barcode (checks DB, then providers){"code": "4012345678901"}
GET /api/products- List products (with optional?query=search)POST /api/products- Manually create productGET /api/products/{id}- Get product by ID
GET /api/inventory- List inventory items (with optional?location=filter)POST /api/inventory- Create inventory itemGET /api/inventory/{id}- Get inventory itemPOST /api/inventory/{id}/adjust- Adjust quantity (Β±delta){"delta": 5, "reason": "add"}
id(UUID, primary key)gtin(string, unique, indexed) - EAN/UPC barcodename(string) - Product namebrand(string, nullable)image_url(string, nullable)source(enum: manual|openfoodfacts|...)raw_payload(JSONB, nullable) - Original provider responsecreated_at,updated_at(timestamps)
id(UUID, primary key)product_id(FK β Product)location(string) - e.g., "Schrank A / Fach 3 / Box 2"quantity(numeric)unit(string, default "pcs")notes(text, nullable)created_at,updated_at(timestamps)
id(UUID, primary key)inventory_item_id(FK β InventoryItem)delta(integer) - Quantity changereason(enum: add|remove|adjust)created_at(timestamp)
# Database
POSTGRES_USER=inventory
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=inventory
DATABASE_URL=postgresql+asyncpg://inventory:your_secure_password_here@postgres:5432/inventory
# Backend
BARCODE_PROVIDERS=openfoodfacts,opengtindb,upcitemdb # Comma-separated list
CORS_ORIGINS=http://localhost:5173,http://localhost
# Frontend
VITE_API_BASE_URL=/api- Ensure PostgreSQL container is healthy:
docker compose ps - Check logs:
docker compose logs postgres
- Backend runs
alembic upgrade headon startup - Check backend logs:
docker compose logs backend - Manually run:
docker compose exec backend alembic upgrade head
- In development: Backend CORS middleware should allow origins from
CORS_ORIGINS - In production: nginx proxies all requests (same-origin, no CORS needed)
- HTTPS required for camera access (or localhost)
- Check browser permissions
- Use manual input as fallback
This project is licensed under the MIT License - see the LICENSE file for details.
The MIT License is a permissive open source license that allows you to:
- β Use commercially
- β Modify
- β Distribute
- β Use privately
- β Sublicense
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request