Turn any shop into a digital storefront in 2 minutes.
QR menu & catalog SaaS for the shop around the corner — create a menu, share a QR code, and receive orders on WhatsApp.
🔗 Live: https://shopqr-nine.vercel.app/
- Screenshots
- Features
- Tech Stack
- Getting Started
- Deployment
- Plans
- Project Structure
- Security Model
- Roadmap
| Feature | Description | |
|---|---|---|
| 01 | Catalog in minutes | Add products, categories and photos. Drag to reorder. |
| 02 | QR that looks yours | Rounded, gradient or branded QR codes. PNG and SVG, print-ready. |
| 03 | Orders on WhatsApp | Every product has an Order now button with the message pre-filled. |
| 04 | See what works | Views, QR scans, clicks and your most popular products. |
| 05 | Seasonal themes | Diwali, Christmas, New Year or Summer — your branding stays. |
| 06 | AI descriptions | Type a product name (e.g. "Samosa") and get a menu-ready description, powered by Gemini. |
| Layer | Technology |
|---|---|
| Frontend | Next.js 15 (App Router, SEO metadata) |
| Backend | Express.js |
| Database | MongoDB (Atlas) |
| AI | Google Gemini (template fallback if no key) |
| Media | Cloudinary |
| Hosting | Vercel (web) · Render (API) |
| DevOps | Docker Compose · GitHub Actions CI |
Prerequisites: Node.js 22+ and a MongoDB instance (local via Docker, or Atlas).
# 1. Install all dependencies
npm run install:all
# 2. Configure environment
# - Server values from .env.example -> server/.env
# - Client value -> client/.env.local
# 3. Start the API and the web app (in separate terminals)
npm run dev:server
npm run dev:clientOpen http://localhost:3000.
- A demo shop is seeded at
/shop/demo. - To become an admin, enter
ADMIN_CODEunder Account → Admin access.
docker compose upStarts the local API and MongoDB.
Follow these steps in order.
- MongoDB Atlas — Create a free cluster, add a database user, and under Network Access allow
0.0.0.0/0(Render has no fixed IP). Copy themongodb+srv://connection string. - Render (API) — New Blueprint from this repo (
render.yamlincluded). SetMONGO_URI,GEMINI_API_KEY,CLOUDINARY_URLandADMIN_CODE. LeaveCLIENT_ORIGINempty for now. Open<api-url>/api/health— it must return{"ok":true}. - Vercel (web) — Import the repo, set Root Directory to
client, and setNEXT_PUBLIC_API=<api-url>(no trailing slash). Deploy. - Back on Render — Set
CLIENT_ORIGIN=<vercel-url>and redeploy. - Verify — Run
node server/smoke.mjs <api-url>; every line should show ✓. Then register in the browser and create a shop.
Tip: Use Cloudinary in production. Without it, images are stored inside MongoDB.
| Variable | Where | Purpose |
|---|---|---|
MONGO_URI |
Server | MongoDB connection string |
GEMINI_API_KEY |
Server | AI descriptions (from Google AI Studio) |
CLOUDINARY_URL |
Server | Image uploads |
ADMIN_CODE |
Server | Grants admin access from the dashboard |
CLIENT_ORIGIN |
Server | Allowed web origin for CORS |
NEXT_PUBLIC_API |
Client | Base URL of the API |
| Plan | Products |
|---|---|
| Free | Up to 12 |
| Pro | Unlimited |
Admins can switch plans via:
PATCH /api/admin/shop/:slug
Content-Type: application/json
{ "plan": "pro" }.
├── server/
│ ├── src/index.js # Express API: auth, shop CRUD, uploads, Gemini, public + analytics routes
│ └── smoke.mjs # Post-deploy smoke test
├── client/
│ ├── app/ # Routes: landing, /dashboard, /shop/[slug] (SEO metadata)
│ ├── components/dashboard/ # One component per dashboard section; shared UI in shared.tsx
│ └── lib/ # API client, QR generator
├── docker-compose.yml # Local API + MongoDB
├── render.yaml # Render Blueprint
└── .github/workflows/ci.yml # Build check
- Passwords — bcrypt (cost 12); 8–72 characters with at least one letter and one number. Accounts lock for 15 minutes after 5 wrong attempts; login and register are rate-limited.
- Sessions — 7-day signed JWTs verified against the database on every request. Changing your password or using Sign out of all devices instantly invalidates every existing token.
- Authorization — Every shop read/write is scoped to the signed-in owner's id. Admin rights are checked in the database, not the token, and the admin code is compared in constant time.
- Input hardening — String-only fields (blocks NoSQL operator injection), validated product ids, strict CORS, security headers (Helmet + Next headers), and a 6 MB body cap.
- Payments (Razorpay / Stripe) — the one piece left before charging for Pro
- Email verification
- "Forgot password" flow
Email features need an email provider such as Resend or Brevo.
[text](../../Downloads/shopqr-readme/shopqr-readme/docs)



