A modern full-stack monorepo for handcrafted ceramics and minimalist home decor.
Overview โข Demo Video โข Architecture โข Features โข Getting Started โข API & Swagger โข Demo Credentials โข Technology Stack
Vessel & Void is an end-to-end e-commerce monorepo managed with pnpm workspaces. It delivers a fast, responsive storefront and admin portal built on React 19 and Vite, a production-grade NestJS REST API with MongoDB persistence, Cloudinary asset storage, Resend email workflows, Razorpay payment processing, and a shared TypeScript package for unified domain models and validation across all layers.
Note
This application follows a decoupled monorepo architecture. Shared domain contracts and constants are defined in @vessel-and-void/shared and imported by both the browser frontend (apps/ui) and the Node.js backend API (apps/api).
A walkthrough demonstration of the full applicationโincluding authentication, customer storefront browsing, admin studio dashboard, category management, and new product creation with Cloudinary image upload:
Tip
The demo video is stored locally in the workspace at ./demo_walkthrough.webm. You can open or play it in any standard browser or video player.
vessel-and-void/
โโโ apps/
โ โโโ ui/ # React 19 Storefront & Admin Portal (@vessel-and-void/ui)
โ โโโ api/ # NestJS REST API Server & MongoDB Mongoose (@vessel-and-void/api)
โโโ packages/
โ โโโ shared/ # Pure TypeScript Domain Contracts & Constants (@vessel-and-void/shared)
โโโ demo_walkthrough.webm # High-definition recorded application demo
โโโ record-demo.mjs # Automated Playwright recording script
A lightweight NodeNext TypeScript library compiled to dist/ providing unified types and schemas:
- Data Models & Types (
src/types/): Pure TypeScript interfaces (IUser,IUserAddress,IUserPreferences,IProduct,ICategory,IOrder,IOrderItem,IReview). - Validation Schemas (
src/schemas/): Zod schemas for runtime validation of auth, user profiles, products, and categories. - Location Constants (
src/constants/location.ts): States, union territories, countries, and regional defaults. - Product & Ceramic Presets (
src/constants/product.ts): Glaze options (Snow,Sage,Charcoal), textures (Matte,Satin,Speckled), badges, and categories. - Navigation Presets (
src/constants/navigation.ts): Top navbar links and footer navigation groupings.
A NestJS REST API connected to MongoDB via Mongoose, providing data persistence, authentication, and file upload capabilities:
- Authentication Module (
src/auth/): JWT authentication strategy viapassport-jwt, password hashing usingbcryptjs(salt 10), email verification tokens, and role-based guards (RolesGuard). - User Management Module (
src/users/): Profile retrieval, profile updates with Cloudinary avatar upload, password changes, and account deletion. - Products Catalog Module (
src/products/): Multi-part file upload with Cloudinary CDN integration, product creation, full-text search, pagination, and category filtering. - Categories Module (
src/categories/): Category hierarchy queries, top-level collection management, display sorting, and admin creation. - Orders & Payments Module (
src/orders/,src/payments/): Order placement, Razorpay payment order generation and webhook verification, tracking code generation (VV-XXXXXX), and order history. - Cloudinary Module (
src/cloudinary/): Media asset upload stream handler supporting product galleries and user avatars. - Mail Module (
src/mail/): Resend email service for account verification and password recovery. - Swagger OpenAPI Documentation (
src/main.ts): Interactive documentation served at/api/docswith Bearer token authentication testing.
A Vite-powered React 19 application built on the Astryx Design System:
- Axios Service Layer (
src/services/api.ts): Type-safe HTTP client with request interceptors to automatically inject JWT Bearer tokens fromlocalStorageand handle responses. - Admin Pages (
src/pages/admin/):AdminDashboardPage.tsx: Real-time sales statistics, product catalog inventory management, and customer order fulfillment table.AddCategoryPage.tsx: Category creation form with SEO meta title/description and homepage display toggles.AddProductPage.tsx: Ceramic product creator with Cloudinary file upload, pricing, inventory stock, glaze selections, surface finishes, and dimensions.
- Storefront & Catalog Screens (
src/pages/):HomePage.tsx: Studio hero, curated collections, craftsmanship feature, testimonials, and newsletter signup.ShopPage.tsx: Filterable product grid, category selectors, sorting, price badges, and quick-add to cart.FeaturedPage.tsx: Showcase of limited-run studio pieces and signature ceramics.AboutPage.tsx: Studio story, clay sourcing philosophy, and artisan workshop details.CheckoutPage.tsx: Shopping bag review, shipping address form, and Razorpay payment checkout.EditProfilePage.tsx: User profile settings, avatar upload, address management, and password updates.
- Responsive modern layout with mobile drawer navigation.
- Storefront homepage featuring curated collections, value propositions, and featured pieces.
- Product catalog grid with category filtering, sorting, price strikethrough badges, and pagination.
- Shopping cart with live badge counters and checkout steps.
- Password hashing with
bcryptjs(salt 10). - Passport JWT bearer token authorization (
JwtAuthGuard&RolesGuard). - Protected routes on client (
ProtectedRoute,AdminRoute) and backend endpoints. - Email verification and password recovery via Resend.
- Interactive studio admin dashboard with KPI stats (Revenue, Orders, Active Products).
- Multi-file image upload directly to Cloudinary storage with thumbnail previews.
- Dynamic category creation with display ordering, visibility toggles, and SEO meta tags.
- Dynamic ceramic product management with pricing, inventory units, glaze selections, and surface finishes.
- Node.js 20.x or higher (v24.x recommended)
- pnpm 10.x or higher
- MongoDB (local instance or MongoDB Atlas URI)
Install all dependencies across the monorepo from the root workspace directory:
pnpm installCreate .env in apps/api/:
PORT=5000
MONGODB_URI=mongodb+srv://<username>:<password>@cluster0.mongodb.net/vessel-and-void?retryWrites=true&w=majority
JWT_SECRET=your_super_secret_jwt_key_here
JWT_EXPIRES_IN=7d
RESEND_API_KEY=your_resend_api_key
EMAIL_FROM="Vessel & Void <onboarding@resend.dev>"
APP_URL=http://localhost:5173
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_cloudinary_api_key
CLOUDINARY_API_SECRET=your_cloudinary_api_secret
CLOUDINARY_FOLDER=vessel-and-voidCreate .env in apps/ui/:
VITE_API_URL=http://localhost:5000/api
VITE_CURRENCY_CODE=INR
VITE_CURRENCY_LOCALE=en-IN
VITE_RAZORPAY_KEY_ID=rzp_test_your_key_idRun both the React UI and NestJS API concurrently from the root directory:
pnpm startOr run services individually:
# Start NestJS API Backend (http://localhost:5000/api)
pnpm start:api
# Start React UI Frontend (http://localhost:5173)
pnpm start:uiBuild all workspace packages in dependency order (packages/shared -> apps/ui & apps/api):
pnpm run buildThe NestJS backend auto-generates interactive Swagger OpenAPI documentation:
- Swagger UI:
http://localhost:5000/api/docs - Base API Path:
http://localhost:5000/api
Tip
You can authorize API requests directly inside Swagger UI by clicking the Authorize button and pasting your JWT Bearer token returned from /api/auth/signin.
| Module | Endpoint | Method | Guard | Description |
|---|---|---|---|---|
| Auth | /api/auth/signup |
POST |
Public | Register new user account |
| Auth | /api/auth/signin |
POST |
Public | Authenticate user & get JWT token |
| Auth | /api/auth/verify-email |
GET/POST |
Public | Verify email address with token |
| Auth | /api/auth/resend-verification |
POST |
Public | Resend email verification link |
| Auth | /api/auth/forgot-password |
POST |
Public | Request password reset email |
| Auth | /api/auth/reset-password |
POST |
Public | Reset password with token |
| Auth | /api/auth/me |
GET |
JWT | Get current authenticated user |
| Users | /api/users/profile |
GET |
JWT | Fetch user profile & address |
| Users | /api/users/profile |
PUT |
JWT | Update profile, address & avatar (Cloudinary) |
| Users | /api/users/change-password |
POST |
JWT | Change account password |
| Users | /api/users/delete-account |
DELETE |
JWT | Delete user account |
| Products | /api/products |
GET |
Public | Query products with category & text search |
| Products | /api/products/:idOrSlug |
GET |
Public | Lookup product details by ID or slug |
| Products | /api/products |
POST |
Admin | Create product with Cloudinary image upload |
| Products | /api/products/:id |
PUT |
Admin | Update product details & images |
| Products | /api/products/:id |
DELETE |
Admin | Delete product from catalog |
| Categories | /api/categories |
GET |
Public | Fetch all visible category collections |
| Categories | /api/categories/:idOrSlug |
GET |
Public | Get single category details |
| Categories | /api/categories |
POST |
Admin | Create new collection category |
| Categories | /api/categories/:id |
PUT |
Admin | Update category details |
| Categories | /api/categories/:id |
DELETE |
Admin | Delete category |
| Orders | /api/orders |
POST |
JWT | Submit order from shopping cart |
| Orders | /api/orders/my-orders |
GET |
JWT | Fetch authenticated user order history |
| Payments | /api/payments/create-razorpay-order |
POST |
JWT | Initialize Razorpay payment order |
| Payments | /api/payments/verify-payment |
POST |
JWT | Verify payment signature and mark paid |
| Route | View | Component | Description |
|---|---|---|---|
/ |
Storefront | HomePage |
Hero showcase, category grid, craftsmanship section |
/shop |
Catalog | ShopPage |
Full ceramic catalog with filters & pagination |
/featured |
Highlights | FeaturedPage |
Curated highlight ceramics & special runs |
/about |
Studio Story | AboutUsPage |
Studio history, craft philosophy & values |
/profile |
Settings | EditProfilePage |
User profile, avatar upload, address & password |
/checkout |
Order | CheckoutPage |
Shopping cart review, shipping form & payment |
/admin |
Admin | AdminDashboardPage |
Sales KPI stats, product catalog & order fulfillment |
/admin/dashboard |
Admin | AdminDashboardPage |
Full admin overview and data tables |
/admin/add-product |
Admin | AddProductPage |
Form to create products with Cloudinary media upload |
/admin/edit-product/:id |
Admin | AddProductPage |
Edit existing ceramic piece details & images |
/admin/add-category |
Admin | AddCategoryPage |
Form to create collection categories with SEO options |
/signin |
Auth | SignInPage |
Sign-in form with validation |
/signup |
Auth | SignUpPage |
Account registration form |
/forgot-password |
Auth | ForgotPasswordPage |
Request password reset email |
/reset-password |
Auth | ResetPasswordPage |
Set new account password |
* |
404 | NotFoundPage |
Branded not found error page |
- React 19: Modern component-driven UI library.
- TypeScript 6: Static typing across views, state, and services.
- Vite 8: Lightning-fast HMR dev server and production bundler.
- React Router 7: Client-side single page application routing.
- Astryx Design: Theme tokens and accessible UI component system.
- Axios: HTTP client with automatic Bearer token injection.
- Heroicons: Clean vector interface iconography.
- Stripe & Razorpay: Multi-gateway payment checkout SDKs.
- NestJS 11: Modular enterprise Node.js server framework.
- MongoDB & Mongoose 8: Document database with typed schemas and indexing.
- Cloudinary SDK: Cloud image storage, transformations, and asset delivery.
- Resend SDK: Transactional email delivery for verification and resets.
- Passport JWT: Token-based authentication strategy and route guards.
- Bcryptjs: Salted password hashing (10 rounds).
- Class Validator & Transformer: Input DTO validation and sanitization.
- Swagger OpenAPI 3.0: Automated REST API schema generation.
- NodeNext TypeScript: Compiled ESM library for browser & Node.js runtimes.
- Zod: Declarative schema validation shared across client and server.
- pnpm 10 Workspaces: High-performance monorepo package orchestration.