Engineering Professionals & Management Organization Club A production-ready Next.js 15 + Clerk + MongoDB starter template.
| Feature | Description |
|---|---|
| 🔐 Clerk Auth | Email/password + OAuth sign-in, session management |
| 🛡️ RBAC | 3 roles: president, core, member with granular permissions |
| 🗄️ MongoDB | Mongoose schema with indexes, hot-reload safe singleton |
| ⚡ App Router | Next.js 15 with route groups, Server Components, Server Actions |
| 🎨 Premium UI | Dark glassmorphism design, Tailwind CSS, custom animations |
| 📊 Analytics | Aggregated membership stats (pluggable with Recharts/Chart.js) |
| 🌱 Mock Data | One-command seed script with 10 realistic members |
EPMOC_WEB/
├── app/
│ ├── (public)/ # Public route group (no auth required)
│ │ ├── layout.tsx # → Wraps: PublicNavbar + Footer
│ │ ├── page.tsx # → Route: / (Landing Page)
│ │ └── sign-in/[[...sign-in]]/
│ │ └── page.tsx # → Route: /sign-in (Clerk UI)
│ ├── (dashboard)/ # Protected route group
│ │ ├── layout.tsx # → Wraps: DashboardSidebar + Header
│ │ └── dashboard/
│ │ ├── page.tsx # → Route: /dashboard (Overview)
│ │ ├── profile/page.tsx # → Route: /dashboard/profile
│ │ ├── members/page.tsx # → Route: /dashboard/members
│ │ └── analytics/page.tsx # → Route: /dashboard/analytics
│ ├── api/
│ │ └── members/route.ts # REST API: GET + POST /api/members
│ ├── globals.css # Design tokens + component classes
│ └── layout.tsx # Root layout: ClerkProvider + fonts
├── components/
│ ├── public/
│ │ └── PublicNavbar.tsx # Sticky nav with Clerk-aware auth buttons
│ └── dashboard/
│ ├── DashboardSidebar.tsx # Role-filtered nav, collapsible
│ └── DashboardHeader.tsx # Page title + greeting + search
├── lib/
│ ├── db.ts # MongoDB singleton connection
│ ├── rbac.ts # Role checking + permission matrix
│ └── utils.ts # cn(), formatDate(), truncate()
├── models/
│ └── Member.ts # Mongoose schema + TypeScript interface
├── scripts/
│ └── seed.ts # Mock data seeder (npm run seed)
├── middleware.ts # Clerk route protection
├── .env.local # 🔑 Your secrets (never commit!)
├── next.config.ts
├── tailwind.config.ts
└── tsconfig.json
npm installEdit .env.local and replace the placeholder values:
# Get from https://dashboard.clerk.com
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
# Get from https://cloud.mongodb.com
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/epmoc- Go to https://dashboard.clerk.com
- Create a new application
- Copy Publishable Key and Secret Key into
.env.local - Under Redirect URLs, add:
- Sign-in URL:
/sign-in - After sign-in URL:
/dashboard
- Sign-in URL:
npm run seedThis inserts 10 mock members (1 president, 3 core, 6 members) into MongoDB.
npm run devOpen http://localhost:3000.
Roles are stored in Clerk's publicMetadata.
To assign a role to a user:
- Go to Clerk Dashboard → Users → Select a user
- Click Metadata → Public
- Add:
{ "role": "president" } - Save. The role takes effect immediately on the next request.
Available roles:
| Role | What they can do |
|---|---|
president |
Full access: manage members, view analytics, settings |
core |
Edit members, view analytics (no settings) |
member |
View-only: profile + member directory |
Returns all members. Requires authentication.
curl http://localhost:3000/api/members \
-H "Authorization: Bearer <session_token>"Creates a new member. Requires president or core role.
{
"name": "Jane Doe",
"email": "jane@example.com",
"department": "Computer Science",
"role": "member",
"status": "active"
}- Create
app/(dashboard)/dashboard/your-page/page.tsx - Add a nav entry in
components/dashboard/DashboardSidebar.tsxwith therolesarray - Call
await requirePermission("your_action")at the top of the page - If it's a new action type, add it to
lib/rbac.ts
- Next.js 15 — App Router, Server Components
- TypeScript — Full type safety
- Tailwind CSS 3 — Utility-first styling
- Clerk — Authentication + user management
- MongoDB Atlas + Mongoose — Database
- Lucide React — Icons
To add a field to Member (e.g., phone):
- Add to
models/Member.ts:phone?: string;
- Add to the Schema object:
phone: { type: String, trim: true }
- Update
lib/rbac.tsif the new field needs permission gating. - Update the relevant page components to display / edit the field.
This is a starter template. Feel free to extend it with:
- Rich text editor for announcements
- Event management module
- Attendance tracking
- Email notifications (Resend/Nodemailer)
- File uploads (UploadThing)
- Real-time updates (Pusher/Socket.IO)