A production-grade Solar Energy Management SaaS platform built for Ahmedabad's residential, commercial, and industrial sectors.
Real-time telemetry Β· AI-powered insights Β· P2P energy trading Β· Multi-site fleet management Β· Smart EV charging Β· PDF export everywhere
- Overview
- Tech Stack
- Architecture
- Quick Start
- Environment Variables
- Database Setup
- Test Credentials
- Role-Based Dashboards
- Platform Features
- Export & PDF System
- API Reference
- Data Models
- Project Structure
- Key Components
- Deploying to Vercel
EcoPower 2.0 is a full-stack Energy-as-a-Service (EaaS) platform that connects solar energy producers, consumers, and grid operators in a unified ecosystem. Built for the Ahmedabad metropolitan area, it supports three distinct user roles with purpose-built dashboards, real-time data, AI-driven recommendations, and branded PDF export across every feature.
Core value propositions:
- Homeowners monitor solar generation, battery state, and grid interaction in real time
- Enterprises manage multi-site solar fleets with ESG reporting and carbon tracking
- Admins oversee the entire platform β users, devices, billing, firmware, and grid health
- Every role can export invoices, reports, and certificates as branded PDFs
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | Next.js 16 (App Router) + React 19 | SSR/CSR hybrid, role-based routing |
| Backend | Node.js + Express 5 | REST API server on port 5005 |
| Database | MongoDB Atlas + Mongoose 9 | Document store β database: eaas_platform |
| AI | Groq API β LLaMA 3.3 70B Versatile | RAG-powered energy advisor chatbot |
| Maps | React Leaflet + OpenStreetMap | Geographic site distribution |
| Auth | JWT (jsonwebtoken) + bcryptjs | Stateless role-based authentication |
| Payments | Custom Razorpay-style flow | Card / UPI / Netbanking / Wallet |
| PDF Export | jsPDF 4 + jsPDF-AutoTable 5 | Branded PDF generation (invoices, reports, certificates) |
| Charts | Custom SVG + inline bar/donut charts | Zero-dependency data visualization |
| Icons | Lucide React | Consistent icon system |
| Animations | Framer Motion | Page transitions and micro-interactions |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Browser (Next.js) β
β ββββββββββββ ββββββββββββββββ βββββββββββββββββββββ β
β β /admin β β /consumer β β /enterprise β β
β ββββββββββββ ββββββββββββββββ βββββββββββββββββββββ β
β β β
β /api/* proxy (next.config.mjs) β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β HTTP
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β Express API Server (port 5005) β
β βββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββ β
β β Users β β Devices β βTelemetry β β Invoices β β
β βββββββββββ€ ββββββββββββ€ ββββββββββββ€ ββββββββββββββ€ β
β β Plans β β Tickets β β Carbon β β Groq AI β β
β βββββββββββ€ ββββββββββββ€ ββββββββββββ€ ββββββββββββββ€ β
β βPayments β β Subs β βLocations β βNotificationsβ β
β βββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββ β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β Mongoose ODM
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββ
β MongoDB Atlas Cluster β
β Database: eaas_platform β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
API Proxy: Next.js rewrites all /api/* requests to http://localhost:5005/api/* in development. On Vercel, api/index.js handles all /api/* routes as a serverless function.
- Node.js 18+
- npm 9+
- MongoDB Atlas account (or local MongoDB)
git clone https://github.com/neevmodh/EcoPower2.0.git
cd EcoPower2.0-main
npm installcp .env.example .env.local
# Edit .env.local with your valuesnpm run seed:completeCreates: 3 users, 5 Ahmedabad location, 10+ IoT devices, 6 months of telemetry, energy plans, 60 invoices, carbon stats, support tickets, subscriptions.
npm run server
# Backend running on port 5005npm run dev
# Frontend running on http://localhost:3000Create .env.local in the project root:
# MongoDB β database name must be eaas_platform
MONGODB_URI=mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net/eaas_platform
# Groq AI (get from https://console.groq.com)
GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_GROQ_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# JWT
JWT_SECRET=your_super_secret_jwt_key_here
NEXTAUTH_SECRET=your_nextauth_secret_here
# App URLs
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXTAUTH_URL=http://localhost:3000Note:
NEXT_PUBLIC_GROQ_API_KEYis used as a client-side fallback when the backend proxy is unavailable.
Connection string format:
mongodb+srv://<username>:<password>@<cluster>.mongodb.net/eaas_platform
The database name must be eaas_platform (underscore, not dash).
Available seed scripts:
| Script | Command | Description |
|---|---|---|
| Full seed | npm run seed:complete |
All data β users, devices, telemetry, invoices |
| Ahmedabad seed | npm run seed |
Location-specific Ahmedabad data |
| Demo profiles | node server/seed_demo_profiles.js |
Additional demo user profiles |
| Role | Password | Access | |
|---|---|---|---|
| Admin | admin@ecopower.com | password123 | Full platform control |
| Enterprise | vikram@techcorp.in | password123 | Multi-site fleet management |
| Consumer | rahul.sharma@gmail.com | password123 | Home solar dashboard |
| Page | Route | Features |
|---|---|---|
| Dashboard | /admin |
KPI overview, live metrics, revenue chart, device health |
| Users & Tenants | /admin/users |
Full CRUD β create, edit, suspend, delete users |
| Devices | /admin/devices |
IoT device registry, status monitoring, serial tracking |
| Energy Plans | /admin/plans |
Create/edit subscription plans |
| Revenue | /admin/billing |
Invoice management, bulk PDF export, payment status |
| Support Queue | /admin/support |
Ticket management with priority, status, assignment |
| Analytics | /admin/analytics |
Time-filtered charts (7d/30d/90d/1y), CSV export |
| Firmware | /admin/firmware |
OTA update management, version tracking |
| Weather Forecast | /admin/weather-forecast |
7-day solar irradiance forecast for Ahmedabad |
| Blockchain | /admin/blockchain |
Immutable audit trail for energy transactions |
| Grid Balancing | /admin/grid-balancing |
Real-time grid load management |
| Page | Route | Features |
|---|---|---|
| Dashboard | /consumer |
Live energy flow, 24h chart, devices, sustainability, billing tabs |
| Analytics | /consumer/analytics |
Time-filtered generation/consumption charts |
| Subscription | /consumer/subscription |
5-step plan wizard, PAYG quick-start, upgrade/downgrade |
| Billing | /consumer/billing |
Invoice history, payment flow, PDF download per invoice + bulk export |
| P2P Trading | /consumer/trading |
Buy/sell excess solar energy with neighbors |
| EV Charging | /consumer/ev-charging |
Vehicle management, smart scheduling, nearby stations |
| DISCOM / Grid | /consumer/discom |
Grid tariff comparison, net metering, DISCOM certificate PDF |
| Support | /consumer/support |
Raise and track support tickets |
Consumer Dashboard Tabs: Energy Flow Β· Hourly Chart Β· Devices Β· Impact Β· Billing
PAYG Plan: Rs.6.5/kWh, no fixed monthly fee, no lock-in.
| Page | Route | Features |
|---|---|---|
| Fleet Dashboard | /enterprise |
Fleet KPIs, hourly chart, Ahmedabad map, site leaderboard, ESG board |
| Multi-Site | /enterprise/sites |
Per-site energy data, status, capacity, efficiency |
| Team | /enterprise/team |
Team member management, role assignment |
| Analytics | /enterprise/analytics |
Cross-site aggregated analytics, site comparison |
| Sustainability | /enterprise/sustainability |
Carbon footprint, ESG score, renewable mix, ESG PDF export |
| Subscription | /enterprise/subscription |
Enterprise plan selection (Starter/Growth/Scale) |
| Billing | /enterprise/billing |
Corporate invoices, expandable rows, bulk PDF export |
Enterprise Plans:
| Plan | Price | Sites | Users | Solar |
|---|---|---|---|---|
| Starter | Rs.15,000/mo | 3 | 10 | 50 kW |
| Growth | Rs.35,000/mo | 10 | 50 | 150 kW |
| Scale | Rs.75,000/mo | Unlimited | Unlimited | 500 kW |
EcoPower has a full branded PDF export system across all roles. Every download button generates a professional PDF with the EcoPower dark header, green accent bar, and footer with GST/CIN details.
| Function | File | Used In | Output |
|---|---|---|---|
downloadInvoicePDF(inv) |
InvoicePDF.js |
Consumer/Enterprise/Admin billing | Single tax invoice PDF |
downloadAllInvoicesPDF(invoices, label) |
InvoicePDF.js |
Consumer/Enterprise/Admin billing | Cover + all invoices + summary PDF |
downloadDashboardReport({...}) |
ExportUtils.js |
Consumer dashboard | Energy & billing report PDF |
downloadESGReport({...}) |
ExportUtils.js |
Enterprise sustainability | ESG sustainability report PDF (2 pages) |
downloadAnalyticsCSV({...}) |
ExportUtils.js |
Admin analytics | Analytics data CSV |
downloadSubscriptionInvoicePDF(inv) |
ExportUtils.js |
Consumer/Enterprise subscription | Subscription invoice PDF |
downloadDISCOMCertificate() |
ExportUtils.js |
Consumer DISCOM page | Net-metering approval certificate PDF |
Tax Invoice (downloadInvoicePDF):
- Branded header with company details
- Invoice number, billing period, due date, energy consumed
- Charges breakdown table (base + GST + discount)
- Energy usage progress bar
- Summary card with totals
- Payment instructions (if unpaid) or confirmation (if paid)
All Invoices (downloadAllInvoicesPDF):
- Dark cover page with account summary stats
- One full invoice page per invoice
- Final summary table with totals
Dashboard Report (downloadDashboardReport):
- 8 KPI boxes (solar generated, consumed, grid import, solar coverage, money saved, CO2 saved, trees, total paid)
- Full invoice history table
ESG Report (downloadESGReport):
- Green cover page with 5 stat boxes
- Page 2: ESG metrics table with benchmark comparison
DISCOM Certificate (downloadDISCOMCertificate):
- Net-metering approval certificate with GUVNL authority details
- Certificate number, validity, feed-in tariff rate
jsPDF-AutoTable v5 requires explicit plugin registration. The loadJsPDF() helper in both ExportUtils.js and InvoicePDF.js handles this:
async function loadJsPDF() {
const [{ jsPDF }, { applyPlugin }] = await Promise.all([
import('jspdf'),
import('jspdf-autotable'),
]);
applyPlugin(jsPDF); // required for v5 β does not auto-patch prototype
return jsPDF;
}All text uses ASCII-safe strings (no emoji or unicode symbols) to avoid jsPDF Helvetica font crashes.
- Floating chat widget on every page
- RAG knowledge base with EcoPower-specific context
- Role-aware responses (admin/consumer/enterprise mode)
- Suggested questions, timestamps, copy button
- Falls back to direct Groq API if backend proxy fails
- Bell icon in header on all three role panels
- Role-specific notifications
- Auto-seeds on first load if no notifications exist
- Mark as read, mark all read, delete
- Polls every 30 seconds, unread count badge
Multi-step payment wizard (components/PaymentFlow.js):
- Method Selection β Card / UPI / Netbanking / Wallet
- Details Entry β card number with Luhn validation, UPI ID format check
- OTP Verification β 6-digit OTP with 30s resend timer
- Processing β animated progress
- Success / Failure β transaction ID, download receipt
- React Leaflet with OpenStreetMap tiles
- Color-coded markers by location type
- Popup cards with site name, address, type badge
- Create energy listings with price/quantity
- Browse offers, buy flow β payment flow integration
- Transaction history, wallet balance, 7-day market price chart
- Register vehicles with battery/range tracking
- Live battery % animation during charging
- Schedule charging by time + preferred source (solar/grid/any)
- Nearby stations with availability, price, fast-charge badges
- Navigate button opens Google Maps directions
- CO2 offset using India grid emission factor (0.82 kg/kWh)
- Forest equivalent (21 kg CO2 absorbed per tree/year)
- ESG score (0β100) based on renewable mix
- Monthly carbon savings trend chart
All routes prefixed with /api/. Next.js proxies to http://localhost:5005/api/ in dev.
POST /api/users/login Login, returns JWT token
POST /api/users/register Register new user
GET /api/users List all users (admin)
PUT /api/users/:id Update user
DELETE /api/users/:id Delete user
GET /api/devices List devices (role/userId filter)
POST /api/devices Register new device
PUT /api/devices/:id Update device
DELETE /api/devices/:id Remove device
GET /api/telemetry/dashboard Dashboard summary (role/userId/range filter)
GET /api/telemetry Raw telemetry readings
Query params: ?role=admin, ?userId=xxx, ?range=7d|30d|90d|1y
GET /api/invoices List invoices (role/userId filter)
POST /api/invoices Generate invoice
PUT /api/invoices/:id Update invoice status
GET /api/subscriptions Get user subscriptions
POST /api/subscriptions Create subscription
PUT /api/subscriptions/:id Update/upgrade plan
DELETE /api/subscriptions/:id/cancel Cancel subscription
POST /api/subscriptions/:id/pause Pause subscription
POST /api/subscriptions/:id/resume Resume subscription
GET /api/plans List all energy plans
POST /api/plans Create plan (admin)
PUT /api/plans/:id Update plan
DELETE /api/plans/:id Delete plan
GET /api/carbon Carbon stats (aggregated for admin, per-user for consumer)
GET /api/notifications Get notifications
PUT /api/notifications/:id/read Mark one as read
PUT /api/notifications/mark-all-read Mark all as read
DELETE /api/notifications/:id Delete notification
GET /api/tickets List tickets
POST /api/tickets Create ticket
PUT /api/tickets/:id Update ticket (status, priority, reply)
DELETE /api/tickets/:id Delete ticket
POST /api/payments Process payment
GET /api/payments Payment history
GET /api/payment-methods Saved payment methods
POST /api/payment-methods Add payment method
DELETE /api/payment-methods/:id Remove payment method
POST /api/groq Chat with AI advisor
Request body: { message: string, role: string, history: array }
GET /api/locations List locations
POST /api/locations Add location
PUT /api/locations/:id Update location
| Model | Collection | Key Fields |
|---|---|---|
| User | users | name, email, password (hashed), role, organizationId |
| Location | locations | name, address, coordinates {lat,lng}, location_type, userId |
| Device | devices | device_serial, device_type, status, firmware_version, locationId, userId |
| EnergyReading | energyreadings | solarGeneration, consumption, gridImport, gridExport, batteryStateOfCharge, timestamp |
| Invoice | invoices | invoiceId, userId, subscriptionId, totalAmount, status, billingPeriod, dueDate |
| Subscription | subscriptions | userId, planId, locationId, status, billingCycle, startDate |
| EnergyPlan | energyplans | name, basePrice, ratePerKwh, maxKwh, includedSolarKw, targetAudience |
| CarbonStat | carbonstats | subscription_id, carbon_saved_kg, trees_equivalent |
| SupportTicket | supporttickets | userId, subject, description, status, priority, category |
| Notification | notifications | userId, role, title, message, type, read, createdAt |
| Payment | payments | invoiceId, userId, amount, method, status, transactionId |
| PaymentMethod | paymentmethods | userId, type, last4, upiId, bankName, isDefault |
| AuditLog | auditlogs | action, userId, entityType, entityId, timestamp |
ecopower/
βββ app/ # Next.js App Router
β βββ layout.js # Root layout
β βββ page.js # Landing page
β βββ globals.css # Global styles
β βββ login/page.js # Login page
β βββ admin/ # Admin role pages
β β βββ layout.js
β β βββ page.js # Admin dashboard
β β βββ users/page.js
β β βββ devices/page.js
β β βββ plans/page.js
β β βββ billing/page.js
β β βββ support/page.js
β β βββ analytics/page.js
β β βββ firmware/page.js
β β βββ weather-forecast/page.js
β β βββ blockchain/page.js
β β βββ grid-balancing/page.js
β βββ consumer/ # Consumer role pages
β β βββ layout.js
β β βββ page.js # Consumer dashboard
β β βββ analytics/page.js
β β βββ subscription/page.js
β β βββ billing/page.js
β β βββ trading/page.js
β β βββ ev-charging/page.js
β β βββ discom/page.js
β β βββ support/page.js
β βββ enterprise/ # Enterprise role pages
β βββ layout.js
β βββ page.js # Fleet dashboard
β βββ sites/page.js
β βββ team/page.js
β βββ analytics/page.js
β βββ sustainability/page.js
β βββ subscription/page.js
β βββ billing/page.js
β
βββ components/ # Shared React components
β βββ AIAdvisor.js # Floating AI chat widget
β βββ AhmedabadMap.js # Leaflet map
β βββ DashboardLayout.js # Header + sidebar wrapper
β βββ ExportUtils.js # PDF/CSV export helpers (dashboard, ESG, DISCOM, subscription)
β βββ InvoicePDF.js # Invoice PDF generator (single + bulk)
β βββ Modal.js # Dialog component (prop: open)
β βββ NotificationCenter.js # Bell icon + notification panel
β βββ PaymentFlow.js # 5-step payment wizard
β βββ Sidebar.js # Role-aware navigation sidebar
β βββ SmartMeterLive.js # Real-time meter widget
β βββ UserProfile.js # User profile dropdown
β
βββ server/ # Express backend
β βββ index.js # Entry point, route mounting
β βββ db.js # MongoDB connection (eaas_platform)
β βββ models/ # Mongoose schemas
β βββ routes/ # API route handlers
β βββ users.js, devices.js, telemetry.js
β βββ invoices.js, subscriptions.js, plans.js
β βββ carbon.js, notifications.js, tickets.js
β βββ payments.js, payment-methods.js
β βββ locations.js, groq.js
β
βββ api/
β βββ index.js # Vercel serverless entry (imports server/app.js)
β
βββ lib/
β βββ api.js # API helper (auto-detects local vs Vercel)
β βββ groqClient.js # Groq AI client (proxy + direct fallback)
β
βββ context/
β βββ AuthContext.js # JWT auth state, login/logout, role detection
β
βββ next.config.mjs # Next.js config + /api/* proxy rewrite (dev only)
βββ package.json
βββ .env.local # Environment variables (not committed)
Uses open prop (not isOpen):
<Modal open={showModal} onClose={() => setShowModal(false)} title="Title">
{/* content */}
</Modal><PaymentFlow
invoiceId="INV-001"
amount={2499}
onSuccess={(txnId) => console.log('Paid:', txnId)}
onClose={() => setPayModal(false)}
/><AIAdvisor mode="consumer" /> // mode: "admin" | "consumer" | "enterprise"import { downloadInvoicePDF, downloadAllInvoicesPDF } from '@/components/InvoicePDF';
await downloadInvoicePDF(invoice);
await downloadAllInvoicesPDF(invoices, 'Account Name');import { downloadDashboardReport, downloadESGReport, downloadDISCOMCertificate, downloadSubscriptionInvoicePDF, downloadAnalyticsCSV } from '@/components/ExportUtils';import { askGroq } from '@/lib/groqClient';
const response = await askGroq(messages); // tries backend proxy first, falls back to direct API| Token | Value | Usage |
|---|---|---|
| Primary Green | #22C55E |
CTAs, active states, success |
| Dark Green | #16A34A |
Hover states |
| Background | #F8FAFC |
Page background |
| Surface | #FFFFFF |
Cards |
| Text Main | #0F172A |
Headings |
| Text Muted | #64748B |
Labels, secondary text |
| Border | #E2E8F0 |
Card borders |
| Sidebar | #0A0F1E |
Dark sidebar background |
| Admin Accent | #8B5CF6 |
Purple β admin role |
| Enterprise Accent | #38BDF8 |
Blue β enterprise role |
| Consumer Accent | #22C55E |
Green β consumer role |
CSS class .glass-card β white card with border, border-radius 16px, subtle shadow.
This project is deployed at Vercel with the Express backend running as a serverless function.
Vercel
βββ Next.js app β all non-/api routes (CDN + SSR)
βββ api/index.js β all /api/* routes (serverless function)
βββ imports server/app.js (Express)
βββ connects to MongoDB Atlas on cold start
1. Push to GitHub
git add .
git commit -m "deploy"
git push origin main2. Import on Vercel
- Go to vercel.com/new
- Import the GitHub repo
- Framework preset: Next.js (auto-detected)
- Root directory:
.
3. Add Environment Variables in Vercel β Settings β Environment Variables:
| Variable | Notes |
|---|---|
MONGODB_URI |
Must end with /eaas_platform |
GROQ_API_KEY |
From console.groq.com |
NEXT_PUBLIC_GROQ_API_KEY |
Same value, client-side fallback |
JWT_SECRET |
Random 32-char string |
NEXTAUTH_SECRET |
Random 32-char string |
NEXT_PUBLIC_APP_URL |
Your Vercel URL |
NEXTAUTH_URL |
Your Vercel URL |
4. MongoDB Atlas β allow all IPs
In Atlas β Network Access, add 0.0.0.0/0 (Vercel uses dynamic IPs).
| Local | Vercel | |
|---|---|---|
| Frontend | npm run dev (port 3000) |
Vercel CDN |
| Backend | npm run server (port 5005) |
Serverless function |
| API routing | Next.js proxy rewrite | vercel.json routes |
| Env vars | .env.local |
Vercel dashboard |
MIT β built for EcoPower 2.0 Hackathon, Ahmedabad 2026.