Building Nyuzi: Next.js on Vercel, PostgreSQL on AWS Aurora
Nyuzi is a custom African fashion marketplace garments, bags, and accessories with category-specific customization, Stripe checkout, and a buyer/artisan fulfillment loop. This post covers how we deployed on Vercel and wired AWS Aurora PostgreSQL, with a demo mode that works before either is fully configured.
Building Nyuzi: Next.js on Vercel, PostgreSQL on AWS Aurora
I was excited to try the Hack the Zero Stack with Vercel v0 and AWS Databases Hackathon, so I chose a challenge I have experienced myself finding fitting clothes!
Nyuzi is a custom African fashion marketplace for garments, bags, and accessories with category-specific customization, Stripe checkout, and a buyer/artisan fulfillment loop. This post covers how we deployed on Vercel and wired AWS Aurora PostgreSQL, with a demo mode that works before either is fully configured.
Stack
| Layer | Choice |
|---|---|
| App | Next.js 16 (App Router), React 19, Tailwind 4 |
| Hosting | Vercel |
| Database | Aurora PostgreSQL via pg |
| Payments | Stripe Checkout + webhook |
| Auth | NextAuth v4 (demo credentials today) |
Key design: without
DATABASE_URL, The app serves mock catalog data and in-memory orders. With Aurora, reads/writes hit Postgres and lib/data.ts falls back to mocks on query errors so a flaky DB does not kill the storefront.Vercel
Push to GitHub, import the repo on vercel.com/new , set env vars, deploy. Build time is ~1–2 minutes.
What runs where
- Server Components — homepage, artisan profiles, product pages; call
lib/data.tsfor mock vs Aurora. - Server Actions — checkout, measurements, order updates (no separate REST API for most mutations).
- Route handlers — NextAuth, Stripe webhook,
/api/health.
We pin region
iad1 in vercel.json to sit near an Aurora cluster in us-east-1.Minimum env vars
| Variable | Purpose |
|---|---|
NEXTAUTH_SECRET | Session signing |
NEXTAUTH_URL | e.g. https://nyuzi.vercel.app |
NEXT_PUBLIC_APP_URL | Stripe redirects, absolute links |
Optional:
STRIPE_*, DATABASE_URL, DATABASE_SSL=true.Vercel injects
VERCEL_URL; lib/env.ts uses it when NEXT_PUBLIC_APP_URL is unset — handy for preview deploys.Health check —
GET /api/health returns feature flags (database, stripe, mockData). Fastest way to confirm env vars applied after deploy.Demo on Vercel — only the three auth vars needed. Mock catalog, in-memory orders, and demo checkout (
/checkout/success?demo=1) work with no Aurora or Stripe.AWS Aurora
Aurora PostgreSQL holds catalog, orders, and customization snapshots. We chose Postgres for enums,
jsonb, and the standard Node pg driver.Provision
- Create Aurora PostgreSQL in RDS.
- Copy cluster endpoint, db name, user, and password.
- Open the security group to your dev IP or Vercel outbound (production).
1
2
DATABASE_URL=postgresql://user:pass@cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com:5432/nyuzi
DATABASE_SSL=trueIn
lib/db.ts:1
2
3
4
5
6
7
pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: process.env.DATABASE_SSL === "true"
? { rejectUnauthorized: false } : undefined,
max: 10,
connectionTimeoutMillis: 10_000,
});TLS is required for Aurora. Conservative pool size and timeouts matter on serverless — functions are short-lived.
Schema (
database/schema.sql)profiles— buyers/artisans (user_roleenum)artisans— slug, story, gallery asjsonbproducts—garment | bag | accessory, occasion, paletteorders—customization_snapshot jsonb(the payload artisans fulfill from)measurements— buyer body metrics
Setup without psql
1
2
npm run db:test # connectivity
npm run db:setup # schema + seedScripts use the same
pg driver as production.Auth note — Aurora is persistence only. NextAuth owns sessions; production would add Cognito or OAuth and sync to
profiles.Vercel ↔ Aurora flow
1
2
3
Browser → Vercel Server Action → lib/data.ts
↓ DATABASE_URL set ↓ unset / error
pg Pool → Aurora mock-data.tsCheckout (
lib/actions/checkout.ts):- Build typed snapshot (garment measurements, bag Ankara options, accessory beads/brass).
- Stripe configured → Checkout Session + pending order in Aurora.
- Not configured → demo order (Aurora if DB set, else mock store) → success redirect.
Stripe webhook on Vercel sets
orders.status = paid in Aurora.Why JSONB for customization
Garments, bags, and accessories produce different data shapes. One
customization_snapshot jsonb column on orders beats dozens of nullable columns. TypeScript discriminated unions in the app match what artisans see on /artisan/dashboard.Takeaways
- Demo-first — Vercel + mocks shipped a judge-ready URL before Aurora existed.
- Single data gate —
lib/data.tskeeps dual-mode logic out of pages. - Region alignment — Vercel
iad1+ Auroraus-east-1keeps server-action latency down. - Health endpoint — confirms config without parsing build logs.
- SSL + pooling — non-negotiable for Aurora from serverless.
Checklist
| Step | Command / action |
|---|---|
| Local demo | npm install && npm run dev → :3001, no .env |
| Vercel demo | Auth vars only → deploy → /api/health |
| Production | Aurora → npm run db:setup → add DATABASE_URL → redeploy |
| Payments | Stripe keys + webhook checkout.session.completed |
Nyuzi pairs editorial UI with a Postgres backend that stores exactly what the artisan needs to make the piece — on Vercel, on Aurora, demo-ready from day one.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article