A modern, self-hosted inventory and stock management system built with Nuxt 4 and Cloudflare.
Give it a try: openstock-v2.pages.dev
- User: [email protected]
- Password: 12345678
- Product Management — Track products with SKU, barcode, variants, and categories
- Supplier Management — Manage supplier information, contacts, and product associations
- Automatic Pricing — Calculate selling prices from cost + margin with tax support
- Tax Configuration — Multiple tax rates with default selection
- Stock Movements — Full audit trail of inventory changes (in/out/adjustment)
- Price History — Track price changes over time
- Low Stock Alerts — Get notified when stock runs low
- Dashboard & Charts — Visual analytics for stock levels and movements
- Multi-variant Support — Products with size, color, or other variants
| Category | Technology |
|---|---|
| Framework | Nuxt 4 with Vue 3 Composition API |
| Styling | TailwindCSS |
| Database | Cloudflare D1 (SQLite at the edge) |
| ORM | Drizzle ORM |
| Hosting | Cloudflare Pages |
| Cache/KV | Cloudflare KV |
| Hub | NuxtHub |
| Charts | Chart.js with vue-chartjs |
| Icons | Lucide Icons via @nuxt/icon |
The easiest way to get started is using the installation script:
# Clone the repository
git clone https://github.com/florianjs/openstock.git
cd openstock
# Make the script executable
chmod +x install.sh
# Run the installer (full setup + deployment)
./install.sh| Command | Description |
|---|---|
./install.sh |
Full installation and deployment to Cloudflare |
./install.sh --dev |
Development setup only (no deployment) |
./install.sh --deploy |
Skip setup, deploy existing configuration |
./install.sh --no-deploy |
Full setup without deployment |
./install.sh --help |
Show help message |
The script will:
- ✅ Check prerequisites (Node.js, npm)
- ✅ Install project dependencies
- ✅ Create and configure
.envfile with secure session password - ✅ Authenticate with Cloudflare (opens browser)
- ✅ Create D1 database and KV namespace
- ✅ Update
wrangler.tomlwith resource IDs - ✅ Run database migrations
- ✅ Build and deploy to Cloudflare Pages
If you prefer manual setup or need more control:
npm install# Copy environment template
cp .env.example .env
# Edit .env and set a secure session password (32+ characters)npx wrangler login# Create D1 database
npx wrangler d1 create openstock-db
# Create KV namespace
npx wrangler kv:namespace create openstock_kv
⚠️ After creation, copy the returned IDs towrangler.toml.
# Apply migrations to remote database
for file in migrations/*.sql; do
npx wrangler d1 execute openstock-db --remote --file="$file" --yes
doneAfter the first deployment, add the session password in Cloudflare Dashboard:
- Go to Workers & Pages → openstock-v2 → Settings → Environment variables
- Add variable:
- Name:
NUXT_SESSION_PASSWORD - Value: Copy from your
.envfile (or generate withopenssl rand -base64 32) - Check Encrypt
- Name:
- Save and redeploy
npm run build
npm run deploy:cfStart the development server on http://localhost:3000:
npm run devThe development server uses NuxtHub's local proxy for Cloudflare resources.
| Script | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Build for production |
npm run preview |
Preview production build locally |
npm run deploy:cf |
Build and deploy to Cloudflare Pages |
npm run db:generate |
Generate migrations from schema changes |
The database schema is defined in server/database/schema.ts using Drizzle ORM.
After modifying the schema:
npm run db:generatenpx wrangler d1 execute openstock-db --remote --file=migrations/XXXX_migration.sql --yes├── app/ # Frontend application (Nuxt 4)
│ ├── components/ # Vue components
│ │ ├── ui/ # Reusable UI components
│ │ └── charts/ # Chart components
│ ├── composables/ # Vue composables
│ ├── layouts/ # Page layouts
│ ├── pages/ # File-based routing
│ ├── plugins/ # Nuxt plugins
│ └── assets/ # CSS and static assets
├── server/ # Backend (Nitro)
│ ├── api/ # API endpoints
│ ├── database/ # Drizzle schema
│ └── utils/ # Server utilities
├── migrations/ # SQL migration files
├── documentation/ # Product documentation
├── public/ # Static files
├── install.sh # Automated setup script
├── wrangler.toml # Cloudflare configuration
└── nuxt.config.ts # Nuxt configuration
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/products |
List all products |
POST |
/api/products |
Create a product |
GET |
/api/products/:id |
Get product details |
PUT |
/api/products/:id |
Update a product |
DELETE |
/api/products/:id |
Delete a product |
GET |
/api/categories |
List all categories |
GET |
/api/suppliers |
List all suppliers |
GET |
/api/movements |
List stock movements |
POST |
/api/movements |
Record a stock movement |
GET |
/api/taxes |
List tax rates |
GET |
/api/dashboard/stats |
Dashboard statistics |
GET |
/api/dashboard/charts |
Chart data |
| Variable | Description | Required |
|---|---|---|
NUXT_SESSION_PASSWORD |
Session encryption key (32+ chars) | ✅ |
NUXT_MIGRATE_SECRET |
Secret key to access /api/__migrate in production |
❌ |
NUXT_ADMIN_SECRET_KEY |
Secret key to access admin endpoints (seed/clear) in production | ❌ |
These endpoints are available for database management:
| Endpoint | Description |
|---|---|
POST /api/__seed |
Seed the database with sample data |
POST /api/__clear |
Clear all data (preserves users and settings) |
- Development: Always accessible without authentication
- Production: Requires
NUXT_ADMIN_SECRET_KEYenvironment variable
-
Set
NUXT_ADMIN_SECRET_KEYin your Cloudflare Pages environment:# Generate a secure key openssl rand -hex 32 -
Call the endpoint with the secret key:
Via query parameter:
curl -X POST "https://your-app.pages.dev/api/__seed?key=YOUR_SECRET_KEY"Via header:
curl -X POST -H "x-admin-secret: YOUR_SECRET_KEY" https://your-app.pages.dev/api/__seed
⚠️ Security Note: These endpoints are powerful and should only be used for demo/staging environments. Never expose the secret key publicly.
On first deployment, the users table is automatically created when accessing /api/auth/check or /api/auth/setup. No manual migration is required for initial setup.
For applying all database migrations manually, use the protected /api/__migrate endpoint:
In development:
curl http://localhost:3000/api/__migrateIn production:
- Set
NUXT_MIGRATE_SECRETenvironment variable in Cloudflare Pages - Call the endpoint with the secret header:
curl -H "x-migrate-secret: YOUR_SECRET" https://your-app.pages.dev/api/__migrateYou can also apply migrations directly using Wrangler:
npx wrangler d1 execute openstock-db --remote --file=migrations/XXXX_migration.sql --yesContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Nuxt Documentation
- NuxtHub Documentation
- Cloudflare D1 Documentation
- Drizzle ORM Documentation
- TailwindCSS Documentation
This project is licensed under the MIT License - see the LICENSE file for details.