Browse streetwear, manage a cart and wishlist, and check out
Translation pending
AI summary · website and README
CommerceTypeScript · JavaScriptGitHub @AdamDakdoukOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
AdamDakdouk/nova-streetwear-fashion-shop
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
A mini e-commerce platform built for the Full Stack Engineer take-home assessment: browse a 15-product streetwear catalog with color/size variants, manage a cart and wishlist, and complete a mocked checkout — end to end, fully responsive.
• Backend: Node.js, Express, TypeScript, Mongoose (MongoDB), JWT auth, zod validation, Jest
• Frontend: React, TypeScript, Vite, Tailwind CSS, TanStack Query, Zustand, React Router, Vitest
• Node.js 20+ (built with v24)
• A running local MongoDB instance on mongodb://127.0.0.1:27017 (or update MONGODB_URI)Read the full README ↗A mini e-commerce platform built for the Full Stack Engineer take-home assessment: browse a 15-product streetwear catalog with color/size variants, manage a cart and wishlist, and complete a mocked checkout — end to end, fully responsive.
mongodb://127.0.0.1:27017 (or update MONGODB_URI)# 1. Install all workspace dependencies (root, server, client)
npm install
# 2. Configure the backend
cp server/.env.example server/.env
# edit server/.env: set a real JWT_SECRET; a RESEND_API_KEY (resend.com) for
# OTP emails; MONGODB_URI pointed at a real cluster if not running Mongo
# locally; and the 5 R2_* vars (dash.cloudflare.com) for admin image uploads
# — see notes below, all of these are required at boot
# 3. Seed the database (creates the 15 products + copies product images into
# client/public/products/, creates a demo user, and inserts the default
# homepage hero)
npm run seed
# 4. Run both apps
npm run dev
GET /api/health for a liveness check)Admin dashboard: /admin/login — [email protected] / AdminPass123! (not linked from the storefront UI; add/edit/delete products including image upload, and edit the homepage hero banner — copy, button label, and 1–4 images, with a live preview). See NOTES_BACKEND.md / NOTES_FRONTEND.md for how the role gating works.
Email/OTP: registration, email verification, and password reset send real email via Resend. EMAIL_FROM must be an address on a domain verified in Resend — with a verified domain, anyone can register and receive their own verification code. Resend's shared sandbox sender ([email protected]) needs no DNS setup but only ever delivers to the address the Resend account was registered with, so it works for local testing and not for anyone else. RESEND_API_KEY is required at boot (the server won't start without it).
Admin image uploads: stored on Cloudflare R2 (S3-compatible object storage), not the app's own server — a local-disk approach was tried first and dropped once it was clear it wouldn't survive an actual deploy (see NOTES_BACKEND.md). Needs a bucket with public access enabled and an API token; all 5 R2_* vars are required at boot.
Deployed as a single Vercel project — the React app and the API share one domain, so there is no CORS to configure and no pair of URLs to keep in sync.
| Path | Served by |
|---|---|
/ | the built React app (client/dist) |
/api/* | the Express app, as one serverless function |
vercel.json sets the build command (npm run build -w client), the output directory, the SPA rewrite that stops /products/:id 404ing on refresh, and bakes VITE_API_URL=/api into the build so it can't be forgotten.api/index.ts is a single function that awaits a database connection and hands the request to the unchanged Express app — Express still does all the routing, exactly as it does locally. Every /api/* path is rewritten to it, carrying the original path as a query parameter that the handler puts back on req.url. A catch-all filename (api/[...path].ts) is the tidier way to express that, but Vercel registered it as a single dynamic segment, so /api/products worked while /api/products/:id was rejected at the edge.connectDB memoises its connection on globalThis. A long-running server connects once at boot; a serverless one would otherwise open a fresh pool per request and exhaust the cluster's connection limit.tsconfig.json exists purely so api/ is type-checked. Vercel bundles that file with esbuild and never type-checks it, which would otherwise leave the deployment's most important file the only one nothing verifies.Setting it up:
vercel.json handles the rest.MONGODB_URI, JWT_SECRET, RESEND_API_KEY, R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME, R2_PUBLIC_URL.
Optional: JWT_EXPIRES_IN, EMAIL_FROM.0.0.0.0/0. Vercel's outbound IPs are not fixed, so an allowlist of specific addresses will fail intermittently./api/health returns {"status":"ok"} before testing the storefront.| Command | Description |
|---|---|
npm run dev | Runs backend + frontend together |
npm run seed | Re-seeds the database and copies product images |
npm run test | Runs backend (Jest) and frontend (Vitest) test suites |
npm run build | Type-checks and builds both workspaces |
npm run optimize-images | Re-encodes product photography in place (see below) |
Product images: the source photography is saved at near-lossless quality, which put roughly 9MB of images on a first page load. npm run optimize-images re-encodes media/ and client/public/products/ in place at quality 80 — about 91% smaller with no visible difference at the sizes this UI renders. Both trees get identical treatment on purpose: compressing only the served copy would work until the next npm run seed restored the heavy originals. It is a one-off to run after adding photography, not part of the build, since it is lossy and rewrites files in place.
server/ Express + TypeScript API (models, services, controllers, routes)
client/ React + TypeScript SPA (pages, components, hooks, api clients)
media/ Source product photography (copied into client/public/products by the seed script)
docs/ Architecture reference notes (see below)
localStorage via a persisted Zustand store, not an httpOnly cookie — a known XSS-surface tradeoff accepted for this scope.server/ + client/) rather than split repos — appropriate for this project's scale (one small API, one small SPA, shared review context).