This guide covers installing ShelfWise for both development and production environments.
System Requirements
Server Requirements
PHP : 8.2 or higher
Database : SQLite, MySQL 8.0+, or PostgreSQL 13+
Web Server : Apache, Nginx, or Laravel built-in server (dev only)
Memory : Minimum 512MB RAM (2GB+ recommended for production)
PHP Extensions
The following PHP extensions are required:
BCMath
Ctype
cURL
DOM
Fileinfo
JSON
Mbstring
OpenSSL
PCRE
PDO (with driver for your database)
Tokenizer
XML
GD or Imagick (for PDF generation)
Frontend Requirements
Node.js : 18+ (20 LTS recommended)
npm : 9+ or compatible package manager
ShelfWise uses Vite 7 for frontend builds and requires a modern Node.js version.
Installation Methods
Development
Production
Docker
Development Installation
Clone the repository
git clone https://github.com/your-org/shelfwise.git
cd shelfwise
Install Composer dependencies
Key packages installed:
laravel/framework (^12.0) - Core Laravel framework
inertiajs/inertia-laravel (^2.0) - Server-side Inertia adapter
laravel/fortify (^1.30) - Authentication scaffolding
laravel/sanctum (^4.0) - API token authentication
barryvdh/laravel-dompdf (^3.1) - PDF generation
maatwebsite/excel (^3.1) - Excel import/export
Install npm dependencies
Frontend stack:
React 19 with TypeScript
TailwindCSS 4 with @tailwindcss/vite
Inertia.js React adapter
Radix UI components
ApexCharts for analytics
Lucide React icons
Configure environment
cp .env.example .env
php artisan key:generate
The .env file contains default settings for local development: APP_NAME = ShelfWise
APP_ENV = local
APP_DEBUG = true
APP_URL = http://localhost:8000
DB_CONNECTION = sqlite
QUEUE_CONNECTION = database
CACHE_STORE = database
SESSION_DRIVER = database
MAIL_MAILER = log
Create SQLite database
touch database/database.sqlite
Run migrations
This creates all necessary tables including:
tenants - Multi-tenant organization data
users - Staff members (tenant-scoped)
shops - Store locations
products and product_variants - Inventory items
orders, order_items, order_payments - Sales data
stock_movements - Inventory audit trail
customers - E-commerce customer data
payslips, pay_runs - Payroll data
Start development servers
This runs three concurrent processes:
php artisan serve - Laravel server on port 8000
php artisan queue:listen - Background job processor
npm run dev - Vite HMR server on port 5173
Optional: Seed Sample Data For testing with demo data: Seeders are for development only. Never run seeders in production.
Production Installation
Clone or deploy code
git clone https://github.com/your-org/shelfwise.git /var/www/shelfwise
cd /var/www/shelfwise
Install dependencies (production mode)
composer install --optimize-autoloader --no-dev
npm ci
Build frontend assets
For SSR (server-side rendering): SSR improves initial page load and SEO. Requires running php artisan inertia:start-ssr as a background service.
Configure environment
cp .env.example .env
nano .env
Update critical production settings: APP_ENV = production
APP_DEBUG = false
APP_URL = https://yourdomain.com
DB_CONNECTION = mysql
DB_HOST = 127.0.0.1
DB_PORT = 3306
DB_DATABASE = shelfwise
DB_USERNAME = shelfwise_user
DB_PASSWORD = secure_password_here
QUEUE_CONNECTION = redis
CACHE_STORE = redis
SESSION_DRIVER = redis
REDIS_HOST = 127.0.0.1
REDIS_PASSWORD = null
REDIS_PORT = 6379
MAIL_MAILER = smtp
MAIL_HOST = smtp.mailtrap.io
MAIL_PORT = 2525
MAIL_USERNAME = your_username
MAIL_PASSWORD = your_password
MAIL_FROM_ADDRESS = [email protected]
Run migrations
php artisan migrate --force
The --force flag is required in production. Ensure you have database backups before running migrations.
Optimize application
php artisan config:cache
php artisan route:cache
php artisan view:cache
Set permissions
sudo chown -R www-data:www-data /var/www/shelfwise
sudo chmod -R 755 /var/www/shelfwise
sudo chmod -R 775 /var/www/shelfwise/storage
sudo chmod -R 775 /var/www/shelfwise/bootstrap/cache
Set up queue worker
Create a supervisor configuration at /etc/supervisor/conf.d/shelfwise-worker.conf: [program:shelfwise-worker]
process_name =%(program_name)s_%(process_num)02d
command =php /var/www/shelfwise/artisan queue:work -- sleep =3 -- tries =3 -- max-time =3600
autostart =true
autorestart =true
stopasgroup =true
killasgroup =true
user =www-data
numprocs =2
redirect_stderr =true
stdout_logfile =/var/www/shelfwise/storage/logs/worker.log
stopwaitsecs =3600
Start the worker: sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start shelfwise-worker: *
Schedule Task Runner Add to crontab: Add this line: * * * * * cd /var/www/shelfwise && php artisan schedule:run >> /dev/null 2>&1
Docker Installation (Coming Soon) Docker support is planned for a future release. For now, use Laravel Sail for local Docker development: composer require laravel/sail --dev
php artisan sail:install
./vendor/bin/sail up
Sail is included in require-dev dependencies. It provides a Docker-based development environment.
Database Configuration
Default for local development. Already configured in .env.example: Create the database file: touch database/database.sqlite
Pros : Zero configuration, great for local dev
Cons : Not suitable for production, no concurrent writes
Recommended for production.
Create database and user:
CREATE DATABASE shelfwise CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER ' shelfwise_user '@ 'localhost' IDENTIFIED BY 'secure_password' ;
GRANT ALL PRIVILEGES ON shelfwise. * TO 'shelfwise_user' @ 'localhost' ;
FLUSH PRIVILEGES;
Update .env:
DB_CONNECTION = mysql
DB_HOST = 127.0.0.1
DB_PORT = 3306
DB_DATABASE = shelfwise
DB_USERNAME = shelfwise_user
DB_PASSWORD = secure_password
Run migrations:
Alternative to MySQL.
Create database and user:
CREATE DATABASE shelfwise ;
CREATE USER shelfwise_user WITH ENCRYPTED PASSWORD 'secure_password' ;
GRANT ALL PRIVILEGES ON DATABASE shelfwise TO shelfwise_user;
Update .env:
DB_CONNECTION = pgsql
DB_HOST = 127.0.0.1
DB_PORT = 5432
DB_DATABASE = shelfwise
DB_USERNAME = shelfwise_user
DB_PASSWORD = secure_password
Web Server Configuration
server {
listen 80 ;
listen [::]:80;
server_name yourdomain.com;
root /var/www/shelfwise/public;
add_header X-Frame-Options "SAMEORIGIN" ;
add_header X-Content-Type-Options "nosniff" ;
index index.php;
charset utf-8;
location / {
try_files $ uri $ uri / /index.php?$ query_string ;
}
location = /favicon.ico { access_log off ; log_not_found off ; }
location = /robots.txt { access_log off ; log_not_found off ; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $ realpath_root $ fastcgi_script_name ;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all ;
}
}
Troubleshooting
500 Error: Storage not writable
Ensure storage and bootstrap/cache directories are writable: sudo chmod -R 775 storage bootstrap/cache
sudo chown -R www-data:www-data storage bootstrap/cache
Clear npm cache and retry: npm cache clean --force
rm -rf node_modules package-lock.json
npm install
If using Node 20+, ensure you have compatible versions.
Migration fails with 'table already exists'
Reset the database (development only): php artisan migrate:fresh
This will delete all data. Never use in production.
Vite not connecting in development
Ensure Vite dev server is running: Check that VITE_APP_NAME is set in .env.
Queue jobs not processing
Start the queue worker: Or use the combined dev command:
Verifying Installation
Run these checks to ensure everything is working:
Check PHP version
php -v
# Should show PHP 8.2 or higher
Check required extensions
php -m | grep -E "pdo|mbstring|openssl|tokenizer|xml|ctype|json"
Test database connection
In Tinker: DB :: connection () -> getPdo ();
// Should not throw an error
Verify frontend build
npm run build
# Should complete without errors
Installation successful? Continue to Configuration to set up mail, queues, and other services.
Updating ShelfWise
To update to the latest version:
# Pull latest code
git pull origin main
# Update dependencies
composer install
npm install
# Rebuild frontend
npm run build
# Run new migrations
php artisan migrate
# Clear and recache
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Restart queue workers
php artisan queue:restart
Always backup your database before updating in production.