Initializing
Back to Projects
Year2024
DomainFullstack
AccessOpen Source
Complexity0 / 10
Next.jsHonoPostgreSQLRedisDockerTraefikE-CommerceMonorepo
FullstackProduction

Waffy - Gourmet Herbs & Spices E-Commerce Platform

A premium artisanal spice e-commerce platform built with monorepo architecture featuring Next.js 15 frontend, Hono API, React admin dashboard, and full-stack Docker deployment.

Parsing system architecture diagram...

Technology Stack

LayerTechnologyVersion/Details
Frontend FrameworkNext.js15.0.0
Frontend StylingTailwind CSS4.1.11
AnimationsFramer Motion12.38.0
Backend APIHono4.3.7
Admin FrameworkReact + Vite18.3.1
Admin UIShadcn/UI + Tailwind3.4.3
DatabasePostgreSQL16-alpine
ORMPrismaLatest
Cache & QueueRedis + BullMQ7-alpine
Object StorageMinIOLatest
AuthenticationJWT + bcryptjsLatest
AI IntegrationGoogle Gemini0.24.1
ValidationZod3.23.8
DeploymentDocker + TraefikLatest

Purpose and Philosophy

Waffy (also referred to as Popular Enterprise) is a premium artisanal spice and pickle e-commerce platform designed to showcase and sell authentic Indian handcrafted pickles and pure spices. The project was born from the need to upgrade a legacy Express.js + EJS + SQLite application to a modern, scalable, enterprise-grade platform.

The core philosophy centers on delivering a sensory-rich user experience that reflects the premium nature of artisanal spices. The platform emphasizes heritage flavors, sustainable sourcing storytelling, and modern culinary applications. By building on a monorepo architecture, the project ensures type safety across all layers, shared business logic, and efficient development workflows.

Core Design Principles

  1. Monorepo Architecture: All applications (web, api, admin, worker) reside in a single repository with shared packages for types, database schemas, and utilities. This enables strict TypeScript consistency and easy refactoring.
  1. API-First Design: The frontend is completely decoupled from the backend. The Hono API serves as the single source of truth, enabling future mobile apps, third-party integrations, and AI agent access without duplicating business logic.
  1. Separation of Concerns: The backend follows a strict layered architecture with Controllers (HTTP handling), Services (business logic), and Repositories (data access). This ensures maintainability as the application grows.
  1. Type Safety End-to-End: Zod schemas define validation at both API boundaries (runtime) and TypeScript compile time. The same schemas are shared between frontend and backend via the @popular/types package.
  1. Background Processing: Long-running operations like Telegram notifications, image optimization, and audit log writes are handled by a dedicated worker service using BullMQ, keeping API responses fast.

Architecture Deep Dive

Monorepo Structure

code
spices-pickle-website/
├── apps/
│   ├── web/                    # Customer-facing Next.js 15 frontend
│   │   ├── app/                 # App Router pages
│   │   │   ├── page.tsx         # Homepage
│   │   │   ├── shop/           # Shop with filtering
│   │   │   ├── product/[slug]/ # Product detail page
│   │   │   ├── blog/           # Blog/recipe section
│   │   │   ├── flavor-lab/     # Interactive spice mixer
│   │   │   └── checkout/       # Quote checkout flow
│   │   ├── components/         # React components
│   │   ├── lib/                # Contexts, utilities, API client
│   │   └── public/             # Static assets
│   │
│   ├── api/                     # Hono REST API
│   │   ├── src/
│   │   │   ├── routes/         # API endpoint definitions
│   │   │   ├── services/       # Business logic
│   │   │   ├── middleware/     # Auth, validation, rate-limiting
│   │   │   ├── lib/            # Prisma, Redis, MinIO clients
│   │   │   └── tests/          # Vitest unit tests
│   │   └── package.json
│   │
│   ├── admin/                   # React + Vite Admin Dashboard
│   │   ├── src/
│   │   │   ├── pages/          # Dashboard, Products, Quotes, etc.
│   │   │   ├── components/     # Layout, Charts, UI components
│   │   │   └── lib/            # API client, auth store
│   │   ├── nginx.conf         # Production nginx config
│   │   └── package.json
│   │
│   └── worker/                  # Background job processor
│       ├── src/
│       │   ├── jobs/           # Telegram, image processing
│       │   └── lib/            # Redis, MinIO, logger
│       └── package.json

├── packages/
│   ├── database/               # Prisma schema + migrations
│   └── types/                  # Shared TypeScript types + Zod schemas

├── docker-compose.yml           # Full stack orchestration
├── pnpm-workspace.yaml         # Monorepo configuration
└── project-overview.md         # Architecture documentation

API Layer (Hono)

The Hono API provides a comprehensive RESTful interface:

typescript
// apps/api/src/index.ts
const app = new Hono();

app.use("*", cors());
app.use("*", secureHeaders());
app.use("*", rateLimiter({ windowMs: 900000, max: 100 }));

app.get("/health", (c) => c.json({ status: "ok" }));

app.route("/api/v1", authRoutes);
app.route("/api/v1", productRoutes);
app.route("/api/v1", quoteRoutes);
app.route("/api/v1", categoryRoutes);
app.route("/api/v1", feedbackRoutes);
app.route("/api/v1", contactRoutes);
app.route("/api/v1", complianceRoutes);
app.route("/api/v1", blogRoutes);
app.route("/api/v1", aiRoutes);
app.route("/api/v1/admin", adminRoutes);

Database Schema (Prisma)

The PostgreSQL schema models the entire e-commerce domain:

prisma
model Product {
  id              Int              @id @default(autoincrement())
  name            String
  slug            String           @unique
  categoryId      Int
  category        Category         @relation(fields: [categoryId], references: [id])
  description     String
  mainImage       String?
  gallery         String[]
  badge           String?
  origin          String?
  flavorProfile   String[]
  aromaticProfile Json?
  isActive        Boolean          @default(true)
  variants        ProductVariant[]
  quotes          Quote[]
  createdAt       DateTime         @default(now())
}

model ProductVariant {
  id        Int       @id @default(autoincrement())
  productId Int
  product   Product   @relation(fields: [productId], references: [id])
  size      String
  price     Decimal   @db.Decimal(10, 2)
  costPrice Decimal?  @db.Decimal(10, 2)
}

model Quote {
  id        Int        @id @default(autoincrement())
  name      String
  phone     String
  email     String?
  productId Int
  product   Product    @relation(fields: [productId], references: [id])
  variantId Int
  variant   ProductVariant @relation(fields: [variantId], references: [id])
  quantity  Int
  address   String?
  message   String?
  status    QuoteStatus @default(NEW)
  logs      QuoteLog[]
  createdAt DateTime   @default(now())
}

enum QuoteStatus {
  NEW
  CONTACTED
  NEGOTIATING
  COMPLETED
  CANCELLED
}

Authentication System

JWT-based authentication with token rotation:

  • Access Token: 15-minute TTL, sent in Authorization header
  • Refresh Token: 7-day TTL, stored in HTTP-only cookie
  • Password Hashing: bcrypt with cost factor 12
  • Role-Based Access: SUPER_ADMIN, ADMIN, VIEWER roles
typescript
// Token payload structure
{
  sub: adminId,          // admin user ID
  role: "ADMIN",         // role from AdminRole enum
  iat: timestamp,
  exp: now + 15min       // short-lived for security
}

Key Features and Functionality

1. Customer Frontend (Next.js 15)

The customer-facing website includes:

Pages:

  • Homepage (/): Hero section, featured products, best sellers, categories grid, testimonials, blog section, newsletter signup
  • Shop (/shop): Full product catalog with filtering (category, price, badge), search, sorting (price/name/newest), grid/list toggle
  • Product Detail (/product/[slug]): Image gallery, aromatic radar chart, flavor profile visualization, detailed descriptions, variant selection
  • Blog (/blog): Recipe-style articles with ingredients and instructions
  • Flavor Lab (/flavor-lab): Interactive spice mixing tool (VisualMixer)
  • Checkout (/checkout): Quote request form

Key Components:

  • NavBar.tsx: Full navigation with cart, wishlist, search
  • Hero.tsx: Animated landing hero with glassmorphism
  • ProductDetailsClient.tsx: Full PDP with all interactions
  • FlavorMap.tsx: D3-based geographic origin map
  • RadarChart.tsx: Aromatic profile visualization
  • VisualMixer.tsx: Interactive spice blending tool
  • CulinaryAssistant.tsx: AI-powered cooking assistant (Gemini)
  • SpiceSommelier.tsx: AI spice recommendation engine
  • MolecularPairing.tsx: Ingredient pairing engine

State Management:

  • Cart via React Context (lib/cart-context.tsx)
  • Wishlist via React Context (lib/wishlist-context.tsx)

2. Admin Dashboard (React + Vite)

The admin panel provides complete business management:

Pages:

  • Dashboard: KPI cards, sales charts, recent quotes
  • Products: CRUD with variants, image upload
  • Categories: Category management
  • Quotes: Quote list, status updates, follow-up notes
  • Sales: Sales records, conversion from quotes
  • Feedbacks: Approve/reject customer reviews
  • Contacts: View and reply to contact queries
  • Compliances: Upload/delete compliance certificates
  • Audit Logs: Read-only activity trail
  • Settings: Site-wide configuration (phone, email, Telegram)
  • Reports: Sales by product, quote conversion funnel

Stack:

  • Vite + React 18 + TypeScript
  • TanStack Query for API data fetching
  • Zustand for auth state
  • Shadcn/UI components
  • Recharts for visualizations

3. API Endpoints

Public Endpoints:

MethodEndpointDescription
GET/api/v1/productsList products with filters
GET/api/v1/products/:slugGet single product
GET/api/v1/categoriesList all categories
POST/api/v1/quotesSubmit quote request
GET/api/v1/feedbacksGet approved feedbacks
POST/api/v1/feedbacksSubmit feedback
POST/api/v1/contactsSubmit contact message

Admin Endpoints (JWT Protected):

MethodEndpointDescription
POST/api/v1/admin/auth/loginAdmin login
POST/api/v1/admin/auth/refreshRefresh token
GET/POST/PUT/DELETE/api/v1/admin/productsProduct CRUD
GET/PUT/api/v1/admin/quotesManage quotes
GET/api/v1/admin/audit-logsView audit trail

4. Background Worker

BullMQ-powered worker handles:

  • Telegram Notifications: Real-time alerts for new quotes, contacts, quote status changes
  • Image Optimization: Sharp-based resizing to WebP format
  • Analytics Events: Asynchronous event processing
typescript
// Queue setup
export const notificationQueue = new Queue("notifications", { connection: redis });
export const imageQueue = new Queue("image-processing", { connection: redis });

5. Caching Strategy

Redis caching with strategic TTLs:

DataCache Key PatternTTL
All categoriescategories:all1 hour
Products listproducts:list:{hash}30 min
Single productproduct:{slug}1 hour
Approved feedbacksfeedbacks:approved2 hours
Admin KPIsadmin:kpis5 min

6. File Storage (MinIO)

S3-compatible object storage for:

  • Product images (main + gallery)
  • Compliance documents
  • Admin uploads
typescript
// Bucket structure
popular-uploads/
├── products/{productSlug}/
│   ├── main.webp
│   └── gallery-1.webp
├── compliances/
│   └── fssai-license.pdf
└── misc/
    └── admin-uploads/

Deployment and Infrastructure

Docker Compose Services

The production stack runs seven containers:

yaml
services:
  web:           # Next.js frontend (port 3013 → 3011)
  api:           # Hono API (port 3012 → 3010)
  admin:         # React admin (port 3014 → 80)
  postgres:      # PostgreSQL 16 (port 5435)
  redis:         # Redis 7 (port 6381)
  minio:         # MinIO object storage (ports 9006, 9016)
  worker:        # Background job processor

Traefik Routing

Domain routing configuration:

  • popular.bajali.in → Web frontend
  • api-popular.swaraniretreat.in → API
  • admin-popular.swaraniretreat.in → Admin dashboard
  • minio-popular.swaraniretreat.in → MinIO console

All routes use HTTPS with Let's Encrypt certificates.

Security Implementation

Authentication & Authorization

  • JWT access tokens (15-minute TTL)
  • Refresh token rotation (7-day TTL)
  • bcrypt password hashing (cost factor 12)
  • Role-based access control (SUPER_ADMIN, ADMIN, VIEWER)

API Security

  • Rate limiting (100 requests per 15 minutes)
  • CORS whitelist for allowed origins
  • CSRF protection middleware
  • Secure headers (HSTS, X-Frame-Options, etc.)
  • Brute force protection on login endpoints
  • Zod validation on all inputs

Infrastructure Security

  • Network isolation via Docker networks
  • Traefik dashboard behind basic auth
  • Environment variables for all secrets
  • HTTP-only cookies for refresh tokens

Lessons Learned and Best Practices

What Worked Well

  1. Monorepo Structure: Shared @popular/types package ensures frontend and backend type consistency
  2. Hono Framework: Clean middleware composition, edge-ready, excellent TypeScript support
  3. Prisma ORM: Type-safe queries, easy migrations, excellent PostgreSQL support
  4. BullMQ Workers: Reliable background job processing, automatic retries
  5. Zod Validation: Runtime + compile-time validation, shared schemas between frontend/backend

Areas for Enhancement

  1. Testing Coverage: Unit tests exist but coverage could be expanded
  2. API Documentation: Swagger UI exists but could be more comprehensive
  3. Monitoring: No dedicated observability stack (Prometheus/Grafana)
  4. CI/CD: Deployment is manual, could benefit from GitHub Actions

Future Expansion

The architecture supports:

  • Mobile Apps: Same API serves native mobile clients
  • Multiple Brands: Multi-tenant architecture possible
  • Subscription Model: Recurring billing integration
  • Marketplace: Vendor management extension

Conclusion

Waffy represents a production-grade e-commerce platform built with modern best practices. The monorepo architecture, type-safe code, separated concerns, and containerized deployment provide a solid foundation for scaling. The rich frontend experience with AI-powered features like the Culinary Assistant and Molecular Pairing demonstrates innovative approaches to e-commerce beyond simple product listings.

The project successfully migrated from a legacy Express/SQLite monolith to a modern stack while maintaining the core business functionality and adding significant new capabilities for business growth.

Development Workflow and Commands

Setting Up Development Environment

The project uses pnpm workspaces for monorepo management. After cloning the repository:

bash
# Install all dependencies
pnpm install

# Start all services in development mode
pnpm dev

This launches all applications with hot reloading:

  • Web frontend: http://localhost:3000
  • API: http://localhost:3010
  • Admin: http://localhost:5173

Building for Production

bash
# Build all packages and apps
pnpm build

# Or build individual apps
cd apps/web && pnpm build
cd apps/api && pnpm build
cd apps/admin && pnpm build

Docker Deployment

The project includes comprehensive Docker configuration for production deployment:

bash
# Build and start all services
docker-compose up -d

# View logs
docker-compose logs -f

# Rebuild specific service
docker-compose build web
docker-compose up -d --force-recreate web

Database Operations

bash
# Run Prisma migrations
pnpm prisma migrate deploy

# Generate Prisma client
pnpm prisma generate

# Seed database
pnpm prisma db seed

Key Business Processes

Quote Workflow

The platform uses a quote-based workflow rather than direct purchases:

  1. Customer browses products and selects variants (size/quantity)
  2. Customer submits quote request with contact details
  3. Admin receives Telegram notification of new quote
  4. Admin reviews and updates quote status (CONTACTED, NEGOTIATING)
  5. On successful conversion, quote becomes sales record
  6. Customer is notified of status changes

Product Management

Admins can:

  • Create products with multiple variants (different sizes/prices)
  • Upload main image and gallery images (stored in MinIO)
  • Set product badges (e.g., "Hot", "New", "Best Seller")
  • Define aromatic profiles (spicy, earthy, sweet, floral, pungent)
  • Specify geographic origin with coordinates for FlavorMap
  • Toggle product visibility (active/inactive)

Content Management

The blog section serves as a recipe repository:

  • Recipe-style articles with ingredient lists
  • Step-by-step cooking instructions
  • Integration with product catalog (link ingredients to products)
  • SEO-optimized for discoverability

Performance Optimization

Frontend Optimizations

  • Server-Side Rendering: Next.js App Router provides SSR for SEO
  • Incremental Static Regeneration: Product pages rebuild every hour
  • Image Optimization: WebP format via Sharp processing
  • Bundle Analysis: Code splitting by route

Backend Optimizations

  • Redis Caching: All product and category queries cached
  • Database Indexing: Proper indexes on frequently queried columns
  • Connection Pooling: Prisma manages PostgreSQL connection pool
  • BullMQ Workers: Background processing keeps API fast

Infrastructure Optimizations

  • Traefik: Efficient reverse proxy with automatic SSL
  • MinIO: S3-compatible storage with CDN potential
  • Docker: Efficient container resource allocation

Monitoring and Maintenance

Health Checks

bash
# Check API health
curl https://api-popular.swaraniretreat.in/api/v1/health

# Check container status
docker ps

Log Monitoring

bash
# API logs
docker logs -f popular-api

# Web logs
docker logs -f popular-web

# Worker logs
docker logs -f popular-worker

Backup Strategy

  • PostgreSQL: Nightly pg_dump to volume
  • Redis: AOF persistence enabled
  • MinIO: Bucket replication to external storage
  • Application state: Environment variables versioned in private branch

Troubleshooting Common Issues

Container Won't Start

Check logs: docker-compose logs <service>

Common causes:

  • Environment variables missing
  • Port conflicts on host
  • Volume permission issues
  • Network not created

Database Connection Errors

Ensure:

  • PostgreSQL container is running
  • DATABASE_URL is correct
  • Network allows container-to-container communication

SSL Certificate Issues

  • Verify domain DNS points to server IP
  • Check Let's Encrypt can reach port 80
  • Review acme.json file permissions (must be 600)

Competitive Advantages

Over Legacy System

FeatureLegacyNew System
DatabaseSQLitePostgreSQL
APINoneFull REST API
AdminEJS templatesReact SPA
CachingNoneRedis
Background jobsNoneBullMQ
TypeScriptNoFull

Unique Selling Points

  1. AI-Powered Features: Culinary Assistant, Molecular Pairing, Spice Sommelier
  2. Visual Product Discovery: FlavorMap, RadarChart, VisualMixer
  3. Sensory Storytelling: Aromatic profiles, geographic origins, health benefits
  4. Modern UX: Glassmorphism, smooth animations, mobile-first design
  5. Scalable Architecture: Microservices-ready, cloud-native

This platform demonstrates that artisanal food e-commerce can be both traditional in product offering and cutting-edge in technology implementation.

Architecture Feedback

Spotted a potential optimization or antipattern? Let me know.

Submit a Technical Suggestion