A modern, multi-tenant school management system with a dynamic public-facing website and role-based admin dashboards. Built for educational institutions, the platform combines a rich public frontend with a full-featured content management backend, subscription-based feature gating, and a developer super-admin console.
| Home Page | Admin Dashboard | Notice Board |
|---|---|---|
| TODO | TODO | TODO |
- Dynamic Hero Carousel — Full-width slideshow with school imagery and announcements
- Notice Board — Paginated, searchable notices with PDF preview and starred/pinned notices
- Academic Toppers — Showcase top performers for Class X & XII with photos, scores, and personal messages
- News & Events Timeline — Sliding timeline layout for upcoming events and recent news
- Interactive Sections — Leadership profiles, Teacher directory, Facilities showcase, Testimonials, FAQ accordion, and enquiry/contact form
- SEO Optimized — Open Graph tags, Twitter Cards, JSON-LD structured data (Schema.org School), sitemap, and robots.txt
- Full CRUD for Notices (with PDF upload to Cloudinary), News (with image upload), Events, and Toppers
- Enquiry inbox — view, mark as read, and manage admissions enquiries
- Star/unstar notices (max 4) with drag-free toggle
- Search and filter across all content types
- Multi-tenant school management — create, activate/deactivate, and delete school tenants
- Subscription plan management — assign Basic / Standard / Premium / Custom plans
- Feature toggling — granular enable/disable of Notice Board, News, and Events per school
- Admin account management — create, enable/disable, and delete school administrators
- JWT authentication with HttpOnly cookies and Bearer token fallback
- Role-based access control (
admin/developer) - Feature-gating middleware restricts content modules based on school subscription plan
- Rate limiting, Helmet security headers, CORS whitelisting, MongoDB injection sanitization
- School-scoped data isolation — each admin only sees their own school's content
Schoolwebsite/
├── client/ # React Frontend (Vite)
│ ├── public/
│ │ ├── favicon.ico
│ │ ├── robots.txt
│ │ └── sitemap.xml
│ ├── assets/
│ │ ├── gallery/ # Campus/event slideshow images
│ │ ├── teachers/ # Teacher profile photos
│ │ └── toppers/ # Topper profile photos
│ ├── src/
│ │ ├── components/ # Reusable UI widgets
│ │ │ ├── Layout.jsx
│ │ │ ├── Navbar.jsx
│ │ │ ├── Footer.jsx
│ │ │ ├── FloatingSocialBar.jsx
│ │ │ ├── PdfModal.jsx
│ │ │ ├── SectionHeader.jsx
│ │ │ └── SimpleCarousel.jsx
│ │ ├── config/
│ │ │ └── schoolPlans.js
│ │ ├── data/
│ │ │ ├── adminAuth.js
│ │ │ ├── contentStore.js
│ │ │ └── siteData.js
│ │ ├── pages/
│ │ │ ├── Home.jsx # Landing page (14 sections)
│ │ │ ├── AboutPage.jsx
│ │ │ ├── AcademicsPage.jsx
│ │ │ ├── AdmissionsPage.jsx
│ │ │ ├── ContactPage.jsx
│ │ │ ├── EventsPage.jsx
│ │ │ ├── FacilitiesPage.jsx
│ │ │ ├── GalleryPage.jsx
│ │ │ ├── LeadershipPage.jsx
│ │ │ ├── NoticesPage.jsx
│ │ │ ├── PlaceholderPage.jsx
│ │ │ ├── AdminDashboard.jsx
│ │ │ ├── AdminLogin.jsx
│ │ │ └── DeveloperDashboard.jsx
│ │ ├── services/
│ │ │ ├── api.js # Axios instance + auth interceptor
│ │ │ ├── contentApi.js # CRUD API functions
│ │ │ ├── developerApi.js # Developer endpoints
│ │ │ └── tenant.js # Tenant URL helper
│ │ ├── App.jsx # Route definitions
│ │ ├── main.jsx # Entry point
│ │ └── index.css # Tailwind v4 + custom design system
│ ├── index.html
│ ├── vite.config.js
│ ├── vercel.json
│ └── package.json
│
├── server/ # Express Backend
│ ├── config/
│ │ ├── db.js # MongoDB connection
│ │ ├── cloudinary.js # Cloudinary SDK config
│ │ └── schoolPlans.js # Plan/feature logic
│ ├── controllers/
│ │ ├── authController.js
│ │ ├── developerController.js
│ │ ├── enquiryController.js
│ │ ├── eventController.js
│ │ ├── newsController.js
│ │ ├── noticeController.js
│ │ ├── publicController.js
│ │ └── topperController.js
│ ├── middleware/
│ │ ├── authMiddleware.js # JWT verification, role/feature guards
│ │ ├── errorHandler.js # Global error handler
│ │ └── uploadMiddleware.js # Multer (image/pdf) config
│ ├── models/
│ │ ├── Admin.js
│ │ ├── Enquiry.js
│ │ ├── NewsEvent.js
│ │ ├── Notice.js
│ │ ├── School.js
│ │ ├── Topper.js
│ │ └── UpcomingEvent.js
│ ├── routes/
│ │ ├── authRoutes.js
│ │ ├── developerRoutes.js
│ │ ├── enquiryRoutes.js
│ │ ├── eventRoutes.js
│ │ ├── newsRoutes.js
│ │ ├── noticeRoutes.js
│ │ ├── publicRoutes.js
│ │ └── topperRoutes.js
│ ├── scripts/
│ │ ├── createAdmin.js
│ │ ├── createDeveloper.js
│ │ └── resetAdmin.js
│ ├── utils/
│ │ ├── apiResponse.js
│ │ ├── asyncHandler.js
│ │ └── schoolScope.js
│ ├── app.js
│ ├── server.js
│ └── package.json
│
└── shared/
└── schoolPlans.json # Plan tiers & feature mapping
- Node.js v18+
- MongoDB instance (local or MongoDB Atlas)
- Cloudinary account (for image/PDF uploads)
# Clone the repository
git clone https://github.com/manishkandari9/Schoolwebsite.git
cd Schoolwebsite
# Install backend dependencies
cd server
npm install
# Install frontend dependencies
cd ../client
npm installPORT=5000
NODE_ENV=development
# MongoDB
MONGO_URI=mongodb+srv://<user>:<password>@<cluster>.mongodb.net/<database>
# JWT
JWT_SECRET=your_jwt_secret
JWT_EXPIRES_IN=7d
# Cloudinary
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# Admin credentials (for seeding)
ADMIN_EMAIL=admin@school.com
ADMIN_PASSWORD=your_secure_password
# Developer credentials (for seeding)
DEVELOPER_USERNAME=developer
DEVELOPER_PASSWORD=your_secure_passwordVITE_API_URL=http://localhost:5000/apicd server
npm run dev # Nodemon — hot reload on http://localhost:5000cd server
npm run seed:developer # Creates/updates the developer account
node scripts/resetAdmin.js # Resets the admin account (uses ADMIN_EMAIL/PASSWORD from .env)cd client
npm run dev # Vite dev server on http://localhost:5173| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/auth/login |
Public | Admin/developer login |
| POST | /api/auth/logout |
Public | Clear session |
| GET | /api/auth/me |
Protected | Current user info |
| Method | Endpoint | Feature Gate | Description |
|---|---|---|---|
| GET | /api/notices |
notices |
List all notices |
| GET | /api/notices/starred |
notices |
Starred notices (top 4) |
| GET | /api/notices/:id/pdf |
notices |
Proxy PDF from Cloudinary |
| POST | /api/notices |
notices |
Create notice (PDF upload) |
| PUT | /api/notices/:id |
notices |
Update notice |
| PATCH | /api/notices/:id/star |
notices |
Toggle starred |
| DELETE | /api/notices/:id |
notices |
Delete notice |
| Method | Endpoint | Feature Gate | Description |
|---|---|---|---|
| GET | /api/news |
news |
List news (paginated) |
| POST | /api/news |
news |
Create news (image upload) |
| PUT | /api/news/:id |
news |
Update news |
| DELETE | /api/news/:id |
news |
Delete news |
| Method | Endpoint | Feature Gate | Description |
|---|---|---|---|
| GET | /api/events |
events |
List upcoming events |
| POST | /api/events |
events |
Create event |
| PUT | /api/events/:id |
events |
Update event |
| DELETE | /api/events/:id |
events |
Delete event |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/toppers |
List all toppers |
| POST | /api/toppers |
Create topper |
| PUT | /api/toppers/:id |
Update topper |
| DELETE | /api/toppers/:id |
Delete topper |
| Method | Endpoint | Rate Limit | Description |
|---|---|---|---|
| POST | /api/enquiries |
5/15min | Submit admission enquiry |
| GET | /api/enquiries |
— | List enquiries (protected) |
| PATCH | /api/enquiries/:id/read |
— | Mark as read (protected) |
| DELETE | /api/enquiries/:id |
— | Delete enquiry (protected) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/developer/schools |
List school tenants |
| POST | /api/developer/schools |
Create school |
| PATCH | /api/developer/schools/:id |
Update school |
| DELETE | /api/developer/schools/:id |
Delete school + related data |
| GET | /api/developer/admins |
List all admins |
| POST | /api/developer/schools/:schoolId/admins |
Create admin for school |
| PATCH | /api/developer/admins/:id |
Update admin |
| DELETE | /api/developer/admins/:id |
Delete admin |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/public/school |
Aggregated public data for the active school |
| GET | /api/health |
Server health check |
Not yet implemented. The current architecture uses standard REST API polling. Planned real-time features:
- Socket.io for live notice board updates and enquiry notifications in the admin dashboard
- Toast notifications when new enquiries are submitted
- Live sync of notices/news/events across admin sessions
-
Public visitors browse the school website (Home, About, Academics, Admissions, etc.). Dynamic content (notices, news, events, toppers) is fetched from the backend API via Axios and rendered with React.
-
School administrators log in via
/admin/loginand manage content through the Admin Dashboard — creating notices (with PDF uploads), publishing news (with images), scheduling events, and managing topper profiles. All actions are protected by JWT authentication and feature-gating middleware. -
The Developer (super-admin) accesses
/developer/dashboardto manage school tenants, assign subscription plans, toggle features, and manage admin accounts across all schools. -
Data flow: Every content model has a
schoolreference field, enforcing multi-tenant isolation. TheschoolScope.jsutility ensures that queries are always scoped to the authenticated admin's school (or the active school for public requests). -
Subscription gating: The
requireFeaturemiddleware checks the school's plan-defined features array before allowing access to protected routes. Developer accounts bypass this check. Plans are defined inshared/schoolPlans.json.
cd client
# Build static assets
npm run build
# Deploy (requires Vercel CLI or GitHub integration)
vercel --prodThe client/vercel.json file contains an SPA rewrite rule to route all paths through index.html. Set the environment variable VITE_API_URL to your production backend URL in the Vercel dashboard.
- Push the
server/directory to a new GitHub repository (or use the monorepo root). - On Render Dashboard, create a New Web Service.
- Connect your repository, set:
- Root Directory:
server - Build Command:
npm install - Start Command:
npm start
- Root Directory:
- Add all environment variables from
server/.env(use production values). - Deploy.
- Create a free cluster on MongoDB Atlas.
- Whitelist Render's IP range (or
0.0.0.0/0for development). - Copy the connection string and set it as
MONGO_URIin your Render environment variables.
TODO: Add a Dockerfile and docker-compose.yml for containerized deployment.
- Real-time notifications via Socket.io for admin dashboard updates
- Email notifications — notify admins of new enquiries via Nodemailer
- Student/Parent portal with individual logins, attendance tracking, and grade reports
- Payment gateway integration for fee collection (Razorpay / Stripe)
- File manager — browse, organize, and reuse uploaded PDFs/images across modules
- Dark mode toggle for the public website
- Multi-language support (i18n)
- Analytics dashboard — page views, enquiry trends, user activity
- Docker support — Dockerfile and docker-compose for one-command setup
- CI/CD pipeline — automated testing and deployment with GitHub Actions
TODO: Replace the GitHub and LinkedIn links with your actual profiles.
This project is licensed under the MIT License.