CBAM GPO is a role-based purchasing and education platform for aesthetic medicine clinics, distributors, and CBAM administrators. It lets licensed members buy products at negotiated group purchasing rates, earn points, enroll in education, and track order savings. Distributors manage fulfillment, stock status, and remittance. Administrators oversee members, distributors, regions, education, and monthly payouts.
Member dashboard:
Distributor dashboard:
Admin dashboard:
Member catalogue and regional distributor selection:
Member education catalogue:
Distributor order queue:
Admin remittance view:
The platform has three authenticated portals:
| Portal | Path | Primary users | Main jobs |
|---|---|---|---|
| Member | /member |
Clinics and licensed practitioners | Browse regional distributors, build distributor-specific carts, place GPO orders, track savings, earn points, and enroll in courses. |
| Distributor | /distributor |
Product distributors | Review incoming orders, update fulfillment status, manage product stock, maintain contact/profile details, and review remittance history. |
| Admin | /admin |
CBAM operations team | Monitor global GPO volume, manage members and distributors, configure regions, administer education, and mark remittance as paid. |
- Clinics compare regional distributor options and purchase eligible aesthetic products at discounted GPO pricing.
- Members track retail-versus-GPO savings and earn CBAM Points from product orders.
- Members redeem points or pay with Stripe for online and external education programs.
- Distributors process orders, add tracking details, and keep stock availability current.
- CBAM operations manage distributor coverage, member status, education content, and monthly distributor payouts.
- Finance teams calculate remittance with CBAM margin retained and distributor net amount payable.
| Area | Technology |
|---|---|
| App framework | Next.js 14 App Router, React 18, TypeScript |
| Styling | Tailwind CSS |
| Database | PostgreSQL through Prisma |
| Auth | NextAuth credentials provider with JWT sessions |
| Payments | Stripe Checkout and webhooks |
| Resend | |
| Deployment target | Vercel |
Install dependencies:
pnpm installCreate an environment file:
cp .env.example .envFill in the required values:
DATABASE_URL=
DIRECT_URL=
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
RESEND_API_KEY=
EMAIL_FROM=noreply@cbam.org
NEXT_PUBLIC_APP_URL=http://localhost:3000Generate a NextAuth secret:
openssl rand -base64 32Push the Prisma schema and seed demo data:
pnpm db:push
pnpm db:seedStart the development server:
pnpm devOpen http://localhost:3000.
After seeding the database, these accounts are available:
| Role | Password | |
|---|---|---|
| Member | s.chen@cityclinic.ca |
member123 |
| Distributor | james@aestheticpro.ca |
distributor123 |
| Admin | admin@cbam.org |
admin123 |
| Rule | Behavior |
|---|---|
| GPO price | Retail price less distributor discount percentage |
| Points earned | 2 points per $1 spent on GPO orders |
| Points redemption | 100 points equals $1 toward eligible courses |
| CBAM margin | 10% of gross order value |
| Distributor remittance | 90% of gross order value |
| MOQ validation | Enforced server-side per distributor product |
| Minimum order | Enforced by distributor as either dollar value or unit count |
| Order edits | Orders can be changed only while still processing |
/member- dashboard with savings, points, recent orders, and recent enrollments/member/catalogue- region, distributor, and product selection flow/member/cart- distributor-specific carts, minimum order checks, and checkout/member/orders- member order history and order actions/member/education- online and external education catalogue/member/education/[id]- lesson player and course detail/member/profile- member profile details
/distributor- order and remittance dashboard/distributor/orders- order queue and fulfillment controls/distributor/products- distributor product availability and stock status/distributor/remittance- payout history/distributor/profile- editable distributor contact information
/admin- global overview/admin/orders- cross-distributor order monitoring/admin/remittance- monthly remittance calculation and paid status/admin/members- member management/admin/distributors- distributor management/admin/regions- regional coverage view/admin/education- course and lesson management
| Route | Purpose |
|---|---|
POST /api/orders |
Create an order with MOQ and minimum-order validation |
GET /api/orders |
Fetch the signed-in member's orders |
PATCH /api/orders/[id] |
Update an order, cancel a processing order, or update fulfillment status |
GET /api/catalogue/regions |
Fetch supported country, province, and city coverage |
GET /api/catalogue/distributors |
Fetch distributors and products for a selected region |
POST /api/enrollments |
Enroll in a course through Stripe, points, or free access |
GET /api/credits |
Fetch points balance and transaction history |
PATCH /api/distributor/products/[productId]/stock |
Update distributor product stock status |
PATCH /api/distributor/profile |
Update distributor profile fields |
POST /api/admin/remittance |
Mark a distributor remittance as paid |
POST /api/webhooks/stripe |
Handle Stripe checkout completion |
For local webhook testing:
stripe listen --forward-to localhost:3000/api/webhooks/stripeCopy the generated webhook signing secret into STRIPE_WEBHOOK_SECRET.
The production webhook endpoint is:
https://your-domain.com/api/webhooks/stripe
Required event:
checkout.session.completed
pnpm dev # Start local development server
pnpm build # Generate Prisma client and build the app
pnpm start # Run the production build
pnpm lint # Run Next.js linting
pnpm db:push # Push Prisma schema to the database
pnpm db:migrate # Create and apply a Prisma migration
pnpm db:seed # Seed demo users, distributors, products, and courses
pnpm db:studio # Open Prisma Studioprisma/
schema.prisma Database schema
seed.ts Demo data
src/
app/ App Router pages and API routes
components/ Shared, member, distributor, and admin components
lib/ Auth, database, Stripe, email, and business logic helpers
docs/
screenshots/ README screenshots
The app is designed for Vercel. Set the same environment variables in Vercel that are used locally, then deploy from the connected Git repository or with the Vercel CLI.
Before deploying, confirm:
- Prisma schema has been applied to the production database.
NEXTAUTH_URLandNEXT_PUBLIC_APP_URLmatch the deployed domain.- Stripe webhook endpoint is registered for the deployed URL.
- Production Stripe and Resend keys are configured.
- Demo credentials are removed or replaced if they should not exist in production.







