A full Next.js 16 (TypeScript, App Router) application. No separate backend — all
"API" work happens in Next.js Route Handlers (src/app/api/**) talking directly
to MongoDB via Mongoose.
Public site
- Home, About, Contact (saves to DB), Privacy Policy, Terms of Service
- Tools: Bill Calculator, Solar ROI Calculator, Fuel Price Tracker, State-wise Comparison
- User auth: Signup -> Email OTP verification -> Login -> Forgot/Reset Password (3-step OTP flow)
Admin panel (/admin/...)
- Admin auth: Signup (requires super-admin approval) -> Email OTP verification -> Login -> Forgot/Reset Password
- Dashboard with live platform stats
- Providers & Rates management (add providers, add/edit/delete embedded rate plans)
- Energy Data management (the dataset that powers the public State Comparison + Fuel Tracker tools)
- Articles (content hub, draft/publish)
- Users (list, block/unblock, delete)
- Subscriptions (read-only view)
- Collapsible sidebar + navbar synced via
SidebarContext(same pattern you provided)
Security
- JWT access tokens (15 min) + refresh tokens (30 days), both httpOnly cookies, signed with
jose(edge-safe) - Separate cookie namespaces for users (
cc_access/cc_refresh) and admins (cc_admin_access/cc_admin_refresh) - Passwords hashed with bcrypt (12 rounds)
middleware.tsprotects all/admin/*routes except the admin auth pages- Admin signup requires super-admin
approved: truebefore login works (mirrors your original design)
Data
- MongoDB via Mongoose, models:
User,Admin,Provider(with embeddedrates[]),Article,Subscription,Energy(the previously-empty model — now the core dataset behind the comparison tools),ContactMessage - All content is dynamic, read from/written to the live database — nothing is hardcoded
npm install
cp .env.example .env.local # already pre-filled with your Mongo URI + generated secrets — just review it
npm run devVisit http://localhost:3000
The admin signup flow requires super-admin approval, so you need at least one approved admin to bootstrap the system. Run:
node --env-file=.env.local scripts/seed.mjsThis creates:
- A super admin:
admin@costcircuit.io/ChangeMe123!(override viaSEED_ADMIN_EMAIL/SEED_ADMIN_PASSWORDin.env.local) — change this password after first login - Sample
Energyprice records (electricity/gas/petrol/diesel across a few states) so the tools aren't empty - One sample
Providerwith two rate plans
Log in at /admin/login with the seeded credentials. There's no "approve admin" UI
yet (see Not yet built below) — approve further admin signups by setting
approved: true on their document directly in MongoDB, or by extending the seed script.
See .env.example. Required: MONGODB_URI, JWT_ACCESS_SECRET, JWT_REFRESH_SECRET.
Everything else (SendGrid, Cloudinary, cron secret) is optional — if SENDGRID_API_KEY
is unset, OTP emails are printed to the server console instead of sent, so you can
still test the full signup/verification flow locally without an email provider.
- Push this project to a GitHub repo.
- In Netlify: Add new site -> Import an existing project, pick the repo.
netlify.tomlalready configures@netlify/plugin-nextjs, so build settings are automatic. - In Site settings -> Environment variables, add everything from
.env.example(MONGODB_URI,JWT_ACCESS_SECRET,JWT_REFRESH_SECRET, and optionally the SendGrid/Cloudinary/cron ones). Use different/longer secrets than the dev ones in.env.local. - Important — MongoDB Atlas network access: Netlify serverless functions don't
have static outbound IPs on the free tier. In Atlas -> Network Access, add
0.0.0.0/0(allow from anywhere) or Netlify won't be able to connect to your cluster. - Deploy. After the first deploy, run the seed script once against your production
database (from your machine, pointing
MONGODB_URIat the same Atlas cluster) to create your production super admin.
If Netlify's Next.js runtime ever gives you trouble with a particular route (rare, but can happen with edge cases in newer Next.js versions), this project also deploys cleanly to Vercel with zero config changes as a fallback — just import the repo there instead.
POST /api/cron/update-energy with header x-cron-secret: <CRON_SECRET> nudges
every Energy record's price by a small random amount and updates its 24h change
indicator, simulating live market movement. Wire this up to any external scheduler
(Netlify Scheduled Functions, GitHub Actions cron, cron-job.org, etc.) if you want
the ticker to move on its own between manual admin updates — entirely optional,
since admins can also just edit prices directly in /admin/rates.
src/app/(public)/...— public site, wrapped in(public)/layout.tsx(Navbar/Footer/FAB)src/app/admin/(auth)/...— admin login/signup/verify/forgot pages, no sidebar chromesrc/app/admin/(protected)/...— admin dashboard & CRUD pages, wrapped inAdminShell(sidebar + navbar), guarded server-side in(protected)/layout.tsxand bymiddleware.tssrc/models/— Mongoose schemas (intentionally trimmed down from the very large reference schemas you shared, to what's actually needed for this MVP's features — they can be extended field-by-field later without breaking anything)src/lib/auth.ts— JWT signing/verification + cookie helpers (usesjose, so it works in both middleware/edge and normal API routes)src/lib/db.ts— cached Mongoose connection (serverless-safe)
Not yet built (flagged honestly, not hidden)
Given the "ship fast" priority, these were intentionally left out of v1:
- An "approve pending admins" UI (currently done by hand in MongoDB / via seed script)
- Rich text editor for articles (content is a plain textarea for now)
- Image upload wiring to Cloudinary (the middleware you provided is not yet called from any route)
- Stripe/payment processing for subscriptions (the
Subscriptionmodel exists but nothing creates real paid subscriptions yet) - A user-facing account/dashboard page (login works and issues a session, but there's
no
/accountpage yet to view saved items — easy to add on top of the existing auth)
None of these block deployment or the core "compare energy costs" experience — they're natural next additions whenever you're ready.