Perfume Vault is a premium full-stack fragrance collection platform built for serious perfume collectors. It combines secure authentication, detailed bottle metadata, virtual shelf management, wishlist tracking, and collection analytics in a polished collector-focused interface.
The application is designed to feel like a digital luxury fragrance rack: structured, elegant, and practical enough for daily use.
- Secure user authentication with Laravel Jetstream
- Personal perfume collection management
- Detailed fragrance metadata tracking
- Virtual shelf and rack organization
- Wishlist management with conversion into collection items
- Usage and performance analytics
- Profile management, photo upload, sessions, and optional 2FA
- Versioned API endpoints for future mobile or external clients
- PHP 8.3+
- Laravel 13
- Laravel Jetstream
- Livewire 3 + Volt
- Laravel Sanctum
- Tailwind CSS
- Alpine.js
- Vite
- Pest
- SQLite by default for local development, with architecture ready for MySQL/PostgreSQL
- Create, edit, delete, archive, and duplicate perfumes
- Track:
- brand
- house
- concentration
- gender category
- release year
- batch code
- retail price and current market value
- notes and accord breakdown
- sillage, longevity, projection, and performance
- number of wears and last worn date
- bottle size and remaining juice
- personal notes, memories, and review
- Shelf-based organization
- Section-based arrangement
- Drag-and-drop rack ordering
- Collector-style visual layout
- Add target bottles
- Store target and current prices
- Prioritize wishlist items
- Convert wishlist entries directly into collection records
- Collection value
- Favorite brand
- Most worn perfume
- Seasonal and category breakdowns
- Usage trends
- Accord distribution
The project is structured around separated application layers:
app/
├── Application
├── Contracts
├── Domain
├── Infrastructure
├── Policies
├── Presentation
High-level responsibilities:
Domain: core models and enumsApplication: DTOs, actions, and servicesContracts: repository interfacesInfrastructure: Eloquent repository implementationsPresentation: web controllers, API controllers, requests, and resources
This keeps controller logic thin and business rules out of views.
git clone <your-repo-url> perfume-vault
cd perfume-vaultcomposer installnpm installcp .env.example .envphp artisan key:generateFor the default local SQLite setup:
touch database/database.sqliteThen confirm your .env contains something like:
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/project/database/database.sqliteIf you prefer MySQL or PostgreSQL, update the database settings in .env accordingly.
php artisan migrate:fresh --seedOr use the dedicated demo seeder command:
php artisan vault:seed-demo --fresh --with-test-userphp artisan storage:linkFor a full local development loop:
composer run devThat starts:
- Laravel dev server
- queue listener
- log tailing
- Vite dev server
If you want a simpler setup:
php artisan serve
npm run devThe demo seeder creates this account:
Email: collector@vault.test
Password: password
Perfume Vault includes a dedicated demo seeding command:
php artisan vault:seed-demoUseful options:
php artisan vault:seed-demo --fresh
php artisan vault:seed-demo --with-test-user
php artisan vault:seed-demo --fresh --with-test-userSeeder files:
Run the full test suite:
php artisan testOr directly with Pest:
./vendor/bin/pestRun a specific test:
php artisan test --filter=PerfumeCollectionTestDevelopment:
npm run devProduction build:
npm run build//login/register/dashboard/collection/rack/wishlist/analytics/settings
Authenticated API endpoints are versioned under:
/api/v1/*
Available resources include:
/api/v1/perfumes/api/v1/wishlist/api/v1/analytics
API authentication uses Laravel Sanctum.
php artisan route:list
php artisan migrate:fresh --seed
php artisan vault:seed-demo --fresh --with-test-user
php artisan test
./vendor/bin/pint
npm run build- Strict typing is used throughout application code
- Business logic lives in services and actions
- Repository interfaces abstract persistence
- DTOs are used for application input/output boundaries
- Policies control ownership-sensitive access
- The UI has been customized away from default Jetstream styling
- The current local setup is optimized for a seeded demo workflow
- Demo content is factory-backed and safe to rebuild repeatedly
- The server can be switched to MySQL/PostgreSQL without restructuring the application
- Run the demo seeder
- Log in with the seeded collector account
- Open
/collection - Open
/rack - Open
/analytics - Add your own bottle and watch how the collection updates
This project is open-sourced under the MIT license.