A mobile-first Progressive Web App (PWA) built specifically for Philippine vape shops. Eliminates manual logbooks and spreadsheets with real-time inventory tracking, sales analytics, and staff accountabilityβall accessible from any device with zero hardware dependencies.
VapeTrack PH is a multi-tenant SaaS platform that enables vape shop owners to:
- β Track inventory in real-time across multiple branches and variants (flavors, nicotine levels, colors)
- β Process sales in under 30 seconds with an optimized Point of Sale interface
- β Monitor profits accurately with automated capital vs. revenue calculations
- β Manage staff access via role-based permissions and PIN authentication
- β Generate business insights through comprehensive dashboards and reports
- β Scale operations from single-location to multi-branch seamlessly
Target Market: Small to medium vape shops in the Philippines running on 4G/5G networks.
Before starting, ensure you have:
| Tool | Version | Download Link | Purpose |
|---|---|---|---|
| Node.js | 20.x LTS or higher |
nodejs.org | Runtime environment |
| npm | 10.x (bundled with Node) |
β | Package manager |
| Git | Latest | git-scm.com | Version control |
| VS Code | Latest | code.visualstudio.com | Code editor |
Install these extensions for optimal developer experience:
# Install via VS Code Quick Open (Ctrl+P / Cmd+P)
ext install bradlc.vscode-tailwindcss # Tailwind IntelliSense
ext install dbaeumer.vscode-eslint # ESLint
ext install esbenp.prettier-vscode # Prettier (code formatting)
ext install usernamehw.errorlens # Inline error highlighting
ext install mikestead.dotenv # .env syntax highlighting
ext install supabase.vscode-supabase # Supabase integrationOr manually install from VS Code Marketplace:
- Tailwind CSS IntelliSense (bradlc.vscode-tailwindcss)
- ESLint (dbaeumer.vscode-eslint)
- Supabase (supabase.vscode-supabase) - Optional but helpful
-
Supabase Account (Free Tier)
- Visit: supabase.com
- Create account and new project
- Note: Free tier includes 500MB database, 1GB file storage, 2GB bandwidth
-
Vercel Account (Free Tier) - Deployment only
- Visit: vercel.com
- Sign up with GitHub account
# Clone the project
git clone https://github.com/yourusername/vapetrack-ph.git
cd vapetrack-ph# Install all packages (~200MB download, 1-2 minutes)
npm installThis installs:
- Next.js 16 (App Router)
- Tailwind CSS 4 (styling framework)
- Supabase JS Client (database SDK)
- TanStack Query v5 (server state management)
- Lucide React (icon library)
- shadcn/ui components (via manual copy)
- TypeScript 5 (type safety)
# Copy the example environment file
cp .env.example .env.localEdit .env.local with your Supabase credentials:
# .env.local
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your-publishable-default-key-here
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key # Server-side onlyWhere to find these:
- Go to supabase.com/dashboard
- Select your project
- Click Settings β API
- Copy Project URL and anon public key
# Option A: Using Supabase CLI (Recommended)
# Install Supabase CLI
npm install supabase --save-dev
# Login to Supabase
npx supabase login
# Link to your project
npx supabase link --project-ref your-project-ref
# Apply database migrations
npx supabase db push
# Generate TypeScript types
npx supabase gen types typescript --project-id your-project-ref > types/database.ts# Option B: Manual SQL Execution
# 1. Open Supabase Dashboard β SQL Editor
# 2. Copy contents of `./migrations/001_initial_schema.sql`
# 3. Execute the SQL script
# 4. Manually copy `types/database.example.ts` to `types/database.ts`npm run devOpen http://localhost:3000 in your browser.
Expected behavior:
- β Sign-up page loads
- β Tailwind styles applied (dark theme)
- β No console errors related to Supabase connection
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 16.1.6 | App Router, RSC, Server Actions |
| React | 19.2 | UI library |
| TypeScript | 5.x | Type safety |
| Tailwind CSS | 4.0 | Utility-first styling |
| shadcn/ui | Latest | Component library (copy-paste) |
| TanStack Query | 5.x | Server state management |
| Lucide React | Latest | Icon library (2000+ icons) |
| Zustand | 5.x | Client state (cart, UI) |
| Technology | Purpose |
|---|---|
| Supabase | PostgreSQL database + Auth + Realtime |
| PostgreSQL | Primary database (v15) |
| Row Level Security (RLS) | Multi-tenant data isolation |
| Postgres Functions | Complex transactions (RPCs) |
| Service | Purpose | Free Tier |
|---|---|---|
| Vercel | Hosting + Edge Network | 100GB bandwidth/month |
| Supabase | Database + Auth | 500MB DB, 2GB bandwidth |
| Vercel Analytics | Performance monitoring | 2,500 events/month |
vapetrack-ph/
βββ app/ # Next.js App Router
β βββ (auth)/ # Route group: Authentication pages
β β βββ login/ # Login page
β β βββ signup/ # Sign-up page
β βββ (dashboard)/ # Route group: Protected pages
β β βββ dashboard/ # Analytics dashboard
β β βββ pos/ # Point of Sale
β β βββ inventory/ # Inventory management
β β βββ branches/ # Branch management
β β βββ staff/ # Staff management
β β βββ reports/ # Reports & analytics
β βββ api/ # API routes (serverless functions)
β β βββ webhooks/ # External webhooks (PayMongo, etc.)
β βββ actions/ # Server Actions (mutations)
β β βββ auth.ts # Authentication actions
β β βββ products.ts # Product CRUD
β β βββ sales.ts # Sales processing
β βββ layout.tsx # Root layout (PWA manifest, fonts)
β βββ page.tsx # Landing page (redirects to login)
β βββ globals.css # Global styles + Tailwind imports
β
βββ components/ # React components
β βββ ui/ # shadcn/ui components (Button, Card, etc.)
β βββ pos/ # POS-specific components
β β βββ ProductGrid.tsx # Product selection interface
β β βββ POSCart.tsx # Shopping cart display
β β βββ CheckoutModal.tsx # Checkout flow
β βββ inventory/ # Inventory components
β β βββ ProductForm.tsx # Add/Edit product
β β βββ VariantManager.tsx # Manage product variants
β βββ layouts/ # Shared layouts
β βββ DashboardLayout.tsx # Main app layout
β βββ POSLayout.tsx # Fullscreen POS layout
β
βββ lib/ # Shared utilities
β βββ supabase/ # Supabase client factories
β β βββ client.ts # Browser client
β β βββ server.ts # Server-side client (with auth)
β β βββ middleware.ts # Auth middleware
β βββ utils/ # Helper functions
β β βββ cn.ts # Tailwind class merger
β β βββ formatters.ts # Currency, date formatting
β β βββ validators.ts # Form validation
β βββ hooks/ # Custom React hooks
β βββ useAuth.ts # Authentication hook
β βββ useCart.ts # POS cart state (Zustand)
β βββ useProducts.ts # TanStack Query hooks
β
βββ types/ # TypeScript type definitions
β βββ database.ts # Auto-generated Supabase types
β βββ index.ts # Application-specific types
β
βββ supabase/ # Supabase configuration
β βββ migrations/ # Database migrations (SQL)
β β βββ 001_initial_schema.sql
β β βββ 002_rls_policies.sql
β β βββ 003_rpcs.sql
β βββ seed.sql # Sample data for testing
β
βββ public/ # Static assets
β βββ icons/ # PWA icons (192x192, 512x512)
β βββ manifest.json # PWA manifest
β βββ favicon.ico # Browser favicon
β
βββ docs/ # Documentation
β βββ PRD.md # Product requirements
β βββ ARCHITECTURE.md # Technical architecture
β βββ SCHEMA.md # Database schema
β βββ API_SPEC.md # Backend API spec
β βββ UI_UX.md # Design system
β βββ ROADMAP.md # Implementation roadmap
β βββ README.md # This file
β
βββ .env.example # Environment variables template
βββ .env.local # Your local env vars (git-ignored)
βββ next.config.ts # Next.js configuration
βββ tailwind.config.ts # Tailwind configuration
βββ tsconfig.json # TypeScript configuration
βββ eslint.config.mjs # ESLint configuration
βββ package.json # Dependencies
Every table has an organization_id column. Supabase RLS policies automatically filter queries:
// Application code - NO manual filtering needed
const { data: products } = await supabase
.from('products')
.select('*'); // Returns ONLY current user's organization products
// RLS policy enforces:
// WHERE organization_id = current_user.organization_idKey Rules:
- β
Never write
WHERE organization_id = Xin application code - β Trust RLS policies to enforce tenant isolation
- β Test with multiple organizations to verify RLS works
Two-table approach: products (base info) β product_variants (SKUs, prices, stock)
// Example: Vape juice with 3 nicotine levels
Product: {
id: "prod-001",
name: "Premium Mango Juice",
brand: "Cloud9",
category_id: "juice"
}
Variants: [
{ sku: "PMJ-3MG", name: "3mg", price: 450, capital_cost: 300, stock: 10 },
{ sku: "PMJ-6MG", name: "6mg", price: 450, capital_cost: 300, stock: 5 },
{ sku: "PMJ-12MG", name: "12mg", price: 500, capital_cost: 330, stock: 8 }
]Critical Rules:
- β
All sales reference
product_variants, NOTproducts - β Single-variant products still need one variant (e.g., "Standard")
- β Inventory tracked per variant, not per product
Use Next.js Server Actions (not API routes) for database writes:
// app/actions/products.ts
'use server';
export async function createProduct(formData: FormData) {
const supabase = createServerClient(); // Auto-includes auth
const { data, error } = await supabase
.from('products')
.insert({
name: formData.get('name'),
// organization_id injected by RLS automatically
});
if (error) throw error;
return data;
}Benefits:
- Type-safe by default
- No CSRF tokens needed
- Works with React 19's
useFormState
For fast POS interactions, assume success and rollback on error:
const { mutate } = useMutation({
mutationFn: createSale,
onMutate: async (newSale) => {
// Cancel in-flight queries
await queryClient.cancelQueries({ queryKey: ['sales'] });
// Optimistically update UI
queryClient.setQueryData(['sales'], (old) => [...old, newSale]);
},
onError: (_, __, context) => {
// Rollback on failure
queryClient.setQueryData(['sales'], context.previousSales);
toast.error('Sale failed. Please retry.');
}
});# Start development server
npm run dev
# Run type checking (catches errors before runtime)
npm run build
# Run linter
npm run lint
# Generate Supabase types (after schema changes)
npx supabase gen types typescript --project-id <your-project-ref> > types/database.ts- Read documentation first (PRD, Schema, API Spec)
- Check RLS policies (ensure new tables have tenant isolation)
- Use Server Actions for mutations
- Implement optimistic UI for interactive features
- Test with multiple organizations to verify RLS
# Copy components into your project (don't install as dependency)
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add dialog
# Components are copied to components/ui/
# Customize freely - you own the codeTarget devices: Android phones (5.5" - 6.7" screens)
- Open Chrome DevTools (F12)
- Toggle device toolbar (Ctrl+Shift+M)
- Select iPhone SE (375Γ667) or Pixel 5 (393Γ851)
- Test touch interactions (click = tap)
- Ensure dev server is running:
npm run dev - Find your local IP:
ipconfig(Windows) orifconfig(Mac/Linux) - Access from phone:
http://192.168.x.x:3000 - Note: Phone and PC must be on same WiFi network
# Install Vercel CLI
npm install -g vercel
# Deploy to production
vercel --prodOr use GitHub integration:
- Push code to GitHub
- Import repo in Vercel Dashboard
- Add environment variables (Supabase keys)
- Deploy automatically on every push
Environment Variables to Set:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY(server-side only)
- PRD.md - Product requirements and user stories
- ARCHITECTURE.md - Technical architecture and decisions
- SCHEMA.md - Complete database schema + RLS policies
- API_SPEC.md - Backend API and TypeScript types
- UI_UX.md - Design system and mobile-first patterns
- ROADMAP.md - 4-week implementation plan
β Error: Invalid API key
- Check
.env.localhas correct Supabase keys - Restart dev server after changing env vars:
npm run dev
β Module not found: Can't resolve 'types/database'
- Generate types:
npx supabase gen types typescript --project-id <ref> > types/database.ts
β RLS policies blocking queries
- Verify user's JWT contains
organization_idclaim - Check RLS policies in Supabase Dashboard β Authentication β Policies
β Styles not loading
- Clear
.nextcache:rm -rf .next(Mac/Linux) orrmdir /s .next(Windows) - Restart dev server
To ensure code quality and consistency, we use ESLint and Next.js built-in validation tools.
# Run linting
npm run lint
# Run type-checking and build validation
npm run buildMany vape shops in the Philippines still rely on manual logbooks or unwieldy spreadsheets, leading to inaccurate inventory, lost profits, and limited visibility over staff actions. VapeTrack PH SaaS streamlines retail operations with:
- Real-time inventory tracking
- Sales and profit analytics
- Staff accountability and activity logs
- Multi-branch management
- Multi-tenant (each shop has its own secure workspace)
- Subscription management and billing
- Self-service onboarding and account management
All via a cloud-based, web interface accessible from phones, tablets, or PCs. No installation or server setup required.
To ensure affordability and simplicity:
- β No barcode scanning
- β No receipt printing
- β No hardware dependencies
- β No on-premise/self-hosted version
- Shop Owner: Full access to their shop's workspace, branch and staff management, analytics, subscription management, reporting.
- Staff (Taga-bantay): PIN login, branch selection, sales recording, view limited product info.
- Platform Admin (SaaS): Manages tenants, billing, and platform-wide settings (internal use).
- π Role-based authentication (Owner, Staff, Platform Admin)
- π¬ Multi-branch support per tenant
- π¦ Inventory and product management
- π° Sales, profit, and capital tracking
- π Advanced analytics and reporting (Daily/Weekly/Monthly/Yearly)
- π§Ύ Staff audit logs
β οΈ Low-stock alerts- π’ Multi-tenant architecture (each shop is isolated)
- π³ Subscription & billing management
- π Self-service onboarding and workspace creation
- π Cloud backups and data security
- π± Fully mobile-responsive UI
- Frontend: Next.js 16, React 19, Tailwind CSS 4
- Backend: Nextjs API route, Supabase (serverless backend with real-time queries)
- Database: Supabase(Postgresql)
- Authentication: Supabase Auth
- Payments: PayMongo
- Deployment: Vercel (frontend) + Supabase (Database)
git clone https://github.com/YOUR_USERNAME/vapetrack-ph.git
cd vapetrack-phnpm installCopy .env.example to .env.local and fill in Supabase credentials, PayMongo keys, and other SaaS configs.
npm run devVisit http://localhost:3000 to access the app.
The frontend is optimized for deployment on the Vercel Platform.
- Connect your GitHub repository to Vercel.
- Configure environment variables (refer to
.env.local). - Deploy!
The backend is powered by Supabase.
- Create a new project on Supabase.
- Set up your database schema using the Supabase dashboard or migrations.
- Add the
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_ANON_KEYto your Vercel project settings.
- API_SPEC.md - Complete API specification
- API_IMPLEMENTATION.md - Implementation details
- API_USAGE_EXAMPLES.md - Code examples
- ARCHITECTURE.md - System architecture
- SCHEMA.md - Database schema
- PRD.md - Product requirements document
This project is licensed under the MIT License - see the LICENSE file for details.
Stay updated with the latest changes in the GitHub Releases page.
Contributions, feedback, and bug reports are welcome! Please open Issues and Pull Requests.