AWS Builder Center

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.

Cloud Engineering | Cloud Surfer @ itprobablyrunsoncloud.com

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

LayerChoice
AppNext.js 16 (App Router), React 19, Tailwind 4
HostingVercel
DatabaseAurora PostgreSQL via pg
PaymentsStripe Checkout + webhook
AuthNextAuth 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.ts for 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
VariablePurpose
NEXTAUTH_SECRETSession signing
NEXTAUTH_URLe.g. https://nyuzi.vercel.app
NEXT_PUBLIC_APP_URLStripe 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
  1. Create Aurora PostgreSQL in RDS.
  2. Copy cluster endpoint, db name, user, and password.
  3. 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=true
In 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_role enum)
  • artisans — slug, story, gallery as jsonb
  • products — garment | bag | accessory, occasion, palette
  • orders — 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 + seed
Scripts 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.ts
Checkout (lib/actions/checkout.ts):
  1. Build typed snapshot (garment measurements, bag Ankara options, accessory beads/brass).
  2. Stripe configured → Checkout Session + pending order in Aurora.
  3. 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

  1. Demo-first — Vercel + mocks shipped a judge-ready URL before Aurora existed.
  2. Single data gate — lib/data.ts keeps dual-mode logic out of pages.
  3. Region alignment — Vercel iad1 + Aurora us-east-1 keeps server-action latency down.
  4. Health endpoint — confirms config without parsing build logs.
  5. SSL + pooling — non-negotiable for Aurora from serverless.

Checklist

StepCommand / action
Local demonpm install && npm run dev → :3001, no .env
Vercel demoAuth vars only → deploy → /api/health
ProductionAurora → npm run db:setup → add DATABASE_URL → redeploy
PaymentsStripe 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.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article