Modern, Responsive Next.js Application for the Department of Computer Science and Engineering, SUST.
A high-performance single-page application built with Next.js 16, Redux Toolkit, and Tailwind CSS, providing an intuitive interface for students, faculty, alumni, and administrators.
- Tech Stack
- Features
- Getting Started
- Environment Variables
- Project Structure
- Key Features
- Routing & Navigation
- State Management
- API Integration
- Authentication Flow
- UI Components
- Deployment
- Best Practices
| Category | Technologies |
|---|---|
| Framework | Next.js 16.1 (App Router) |
| Language | TypeScript 5 |
| UI Library | React 19.2 |
| Styling | Tailwind CSS 4, Material UI 7.3 |
| State Management | Redux Toolkit 2.11, RTK Query |
| Forms | React Hook Form 7.71, Zod 4.3 |
| Animations | GSAP 3.14 |
| HTTP Client | Axios 1.13 |
| Rich Text | React Quill (New) |
| Icons | Lucide React |
| Utilities | date-fns, clsx, tailwind-merge |
| Authentication | JWT (jwt-decode, js-cookie) |
| Notifications | React Hot Toast |
-
🏠 Public Homepage
- Dynamic banner carousel
- About the department
- Research areas showcase
- Recent achievements
- Department services
- Responsive design with smooth animations
-
Student Dashboard
- Personal profile overview
- Finance management (conditional access)
- Application submissions (conditional access)
- Work assignments
- Blog authoring
-
Teacher Dashboard
- Faculty profile management
- Course management
- Student oversight
-
Admin Dashboard
- User approval system
- Content management (CMS)
- Homepage customization
- Notices & events management
- Society management
- Finance oversight
- Blog moderation
-
Authentication & Authorization
- JWT-based authentication
- Email verification
- Password reset functionality
- Role-based access control (RBAC)
- Protected routes
-
Content Management
- Blog creation with rich text editor
- Event management with categories
- Notice board
- Homepage content customization
- Image uploads with preview
-
Financial Transparency
- Public income/expense ledger
- Proof document uploads (images/PDFs)
- Category-based filtering
- Real-time updates
-
Academic Resources
- Faculty directory
- Alumni network
- Student profiles
- Batch and session filtering
-
Application System
- Application submission
- Status tracking
- Admin review workflow
-
Society Management
- Hierarchical member structure
- Work assignment system
- Task tracking
- Progress monitoring
- Node.js (v18 or higher)
- npm or yarn
- Backend API (running locally or deployed)
-
Navigate to Frontend directory
cd Frontend -
Install dependencies
npm install
-
Set up environment variables
cp .env.example .env
Edit
.envwith your backend API URL:NEXT_PUBLIC_API_URL=http://localhost:5000/api # OR for production: # NEXT_PUBLIC_API_URL=https://your-backend.vercel.app/api
-
Start development server
npm run dev
-
Open in browser
http://localhost:3000
Create a .env file in the Frontend directory:
# Required: Backend API Base URL
NEXT_PUBLIC_API_URL=http://localhost:5000/api
# Production Example:
# NEXT_PUBLIC_API_URL=https://backend-production-url.vercel.app/apiNote: All environment variables prefixed with
NEXT_PUBLIC_are exposed to the browser.
Frontend/
├── public/ # Static assets
│ ├── images/
│ ├── icons/
│ └── ...
│
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── layout.tsx # Root layout with providers
│ │ ├── page.tsx # Homepage
│ │ │
│ │ ├── about/ # About page
│ │ ├── academic/ # Academic resources
│ │ ├── achievements/ # Department achievements
│ │ ├── alumni/ # Alumni directory
│ │ ├── applications/ # Application system
│ │ │ └── submit/ # Submit application
│ │ ├── blogs/ # Blog listing & details
│ │ ├── events/ # Events listing
│ │ ├── faculty/ # Faculty directory
│ │ ├── finance/ # Financial transparency
│ │ ├── notices/ # Notice board
│ │ ├── profile/[id]/ # User profiles
│ │ ├── projects/ # Research projects
│ │ ├── research/ # Research areas
│ │ ├── services/ # Department services
│ │ ├── societies/ # Society pages
│ │ ├── students/ # Student directory
│ │ │
│ │ ├── login/ # Login page
│ │ ├── register/ # Registration page
│ │ ├── verify/ # Email verification
│ │ ├── forgot-password/ # Password reset request
│ │ ├── reset-password/ # Password reset form
│ │ │
│ │ ├── dashboard/ # User dashboards
│ │ │ ├── student/ # Student dashboard
│ │ │ └── teacher/ # Teacher dashboard
│ │ │
│ │ └── admin/ # Admin panel
│ │ └── dashboard/ # Admin dashboard
│ │ ├── users/ # User management
│ │ ├── blogs/ # Blog management
│ │ ├── events/ # Event management
│ │ ├── notices/ # Notice management
│ │ ├── homepage/ # Homepage CMS
│ │ ├── societies/ # Society management
│ │ └── ...
│ │
│ ├── components/ # Reusable UI components
│ │ ├── common/ # Shared components
│ │ │ ├── Navbar.tsx
│ │ │ ├── Footer.tsx
│ │ │ ├── LoadingSpinner.tsx
│ │ │ └── ProtectedRoute.tsx
│ │ ├── dashboard/ # Dashboard-specific components
│ │ ├── home/ # Homepage sections
│ │ └── admin/ # Admin panel components
│ │
│ ├── features/ # Redux slices & API endpoints
│ │ ├── auth/ # Authentication
│ │ │ ├── authSlice.ts # Auth state management
│ │ │ └── authApi.ts # Auth API endpoints
│ │ ├── user/
│ │ ├── blog/
│ │ ├── event/
│ │ ├── finance/
│ │ ├── content/
│ │ ├── alumni/
│ │ ├── application/
│ │ ├── society/
│ │ ├── payment/
│ │ ├── product/
│ │ └── work-assignment/
│ │
│ ├── store/ # Redux store configuration
│ │ ├── index.ts # Store setup
│ │ └── apiSlice.ts # RTK Query base API
│ │
│ ├── hooks/ # Custom React hooks
│ │ └── useAuth.ts # Authentication hook
│ │
│ ├── utils/ # Utility functions
│ │ ├── api.ts # Axios instance
│ │ └── helpers.ts # Helper functions
│ │
│ └── styles/ # Global styles
│ └── globals.css # Tailwind imports & custom CSS
│
├── .env # Environment variables (not in git)
├── .env.example # Environment template
├── .gitignore
├── next.config.ts # Next.js configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── postcss.config.mjs # PostCSS configuration
├── tsconfig.json # TypeScript configuration
├── package.json
└── README.md
The app implements a complete authentication flow:
// Login
POST /api/auth/login
→ Stores JWT in cookies
→ Updates Redux auth state
→ Redirects to dashboard
// Auto-login on page load
useEffect(() => {
const token = Cookies.get('token');
if (token) {
dispatch(setCredentials({ token, user }));
}
}, []);Protected Routes:
// components/common/ProtectedRoute.tsx
export function ProtectedRoute({ children, allowedRoles }) {
const { user, isAuthenticated } = useAuth();
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
if (allowedRoles && !allowedRoles.includes(user.role)) {
return <Navigate to="/unauthorized" />;
}
return children;
}Role-Based Dashboards:
| Role | Dashboard Route | Features |
|---|---|---|
| Student | /dashboard/student |
Profile, Finance*, Applications*, Work Assignments |
| Teacher | /dashboard/teacher |
Profile, Course Management, Student Oversight |
| Admin | /admin/dashboard |
Full System Control, CMS, User Management |
*Conditional access based on permissions
Admin CMS Features:
- Homepage banner management (image upload, reordering)
- About section editor
- Research areas CRUD
- Services management
- Achievements showcase
- Notice board
- Event calendar
Public Financial Transparency:
// Public ledger accessible to all users
GET /api/finance
→ Returns: Income/Expense records with proof documents
→ Filters: type, category, dateRangeFeatures:
- Category-based organization
- Image/PDF proof uploads
- Real-time balance calculation
- Admin/permitted user entry creation
Blog & Content Creation:
- React Quill integration
- Markdown support
- Image embedding
- Code syntax highlighting
- Draft saving
| Route | Description |
|---|---|
/ |
Homepage |
/about |
About the department |
/faculty |
Faculty directory |
/students |
Student directory |
/alumni |
Alumni network |
/blogs |
Blog listing |
/blogs/[id] |
Blog details |
/events |
Events calendar |
/notices |
Notice board |
/finance |
Financial transparency |
/societies |
Society pages |
/research |
Research areas |
/achievements |
Department achievements |
/services |
Department services |
/projects |
Research projects |
| Route | Description |
|---|---|
/login |
User login |
/register |
New user registration |
/verify |
Email verification |
/forgot-password |
Password reset request |
/reset-password |
Password reset form |
| Route | Roles | Description |
|---|---|---|
/dashboard/student |
Student | Student dashboard |
/dashboard/teacher |
Teacher | Teacher dashboard |
/profile/[id] |
All | User profile |
/applications/submit |
Student | Submit application |
| Route | Description |
|---|---|
/admin/dashboard |
Admin overview |
/admin/dashboard/users |
User management |
/admin/dashboard/blogs |
Blog moderation |
/admin/dashboard/events |
Event management |
/admin/dashboard/notices |
Notice management |
/admin/dashboard/homepage |
Homepage CMS |
/admin/dashboard/societies |
Society management |
{
auth: {
user: User | null,
token: string | null,
isAuthenticated: boolean
},
api: {
// RTK Query cache
queries: { ... },
mutations: { ... }
}
}Each feature module has its own API slice:
// features/blog/blogApi.ts
export const blogApi = apiSlice.injectEndpoints({
endpoints: (builder) => ({
getBlogs: builder.query({ ... }),
getBlogById: builder.query({ ... }),
createBlog: builder.mutation({ ... }),
updateBlog: builder.mutation({ ... }),
deleteBlog: builder.mutation({ ... })
})
});Usage in Components:
import { useGetBlogsQuery, useCreateBlogMutation } from '@/features/blog/blogApi';
function BlogList() {
const { data: blogs, isLoading, error } = useGetBlogsQuery();
const [createBlog, { isLoading: isCreating }] = useCreateBlogMutation();
// Component logic...
}// store/apiSlice.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import Cookies from 'js-cookie';
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: process.env.NEXT_PUBLIC_API_URL,
prepareHeaders: (headers) => {
const token = Cookies.get('token');
if (token) {
headers.set('Authorization', `Bearer ${token}`);
}
return headers;
}
}),
tagTypes: ['User', 'Blog', 'Event', 'Finance', ...],
endpoints: () => ({})
});| Module | Hook | Endpoint | Method |
|---|---|---|---|
| Auth | useLoginMutation |
/auth/login |
POST |
| Auth | useRegisterMutation |
/auth/register |
POST |
| Blog | useGetBlogsQuery |
/blogs |
GET |
| Blog | useCreateBlogMutation |
/blogs |
POST |
| Event | useGetEventsQuery |
/events |
GET |
| Finance | useGetFinanceQuery |
/finance |
GET |
| User | useGetUsersQuery |
/users |
GET |
| Alumni | useGetAlumniQuery |
/alumni |
GET |
graph LR
A[User Registers] --> B[Email Sent]
B --> C[Email Verification]
C --> D[Admin Approval]
D --> E[Access Granted]
-
User Registration (
/register)- Fill registration form
- Submit with role selection
- Account created with
PENDINGstatus
-
Email Verification (
/verify)- Check email for verification link
- Click link to verify email
- Status remains
PENDING
-
Admin Approval (Admin Dashboard)
- Admin reviews pending users
- Approves or rejects
- Status changes to
APPROVED
-
Login (
/login)- Only
APPROVEDusers can log in - JWT token stored in cookies
- Redirected to role-specific dashboard
- Only
// Auto-refresh token before expiry
useEffect(() => {
const token = Cookies.get('token');
if (token) {
const decoded = jwtDecode(token);
const timeUntilExpiry = decoded.exp * 1000 - Date.now();
// Refresh 5 minutes before expiry
const refreshTime = timeUntilExpiry - (5 * 60 * 1000);
const refreshTimer = setTimeout(() => {
refreshToken();
}, refreshTime);
return () => clearTimeout(refreshTimer);
}
}, []);The app uses a combination of:
- Custom Components (Tailwind CSS)
- Material UI (Forms, Dialogs, Data Grids)
components/
├── common/
│ ├── Navbar.tsx # Site navigation with role-based menu
│ ├── Footer.tsx # Footer with links
│ ├── LoadingSpinner.tsx # Loading indicator
│ ├── ProtectedRoute.tsx # Route guard
│ └── ErrorBoundary.tsx # Error handling
│
├── home/
│ ├── HeroSection.tsx # Homepage banner
│ ├── AboutSection.tsx # About the department
│ ├── ResearchAreas.tsx # Research showcase
│ ├── Achievements.tsx # Recent achievements
│ ├── Services.tsx # Department services
│ └── Stats.tsx # Statistics counter
│
└── dashboard/
├── DashboardLayout.tsx # Dashboard container
├── Sidebar.tsx # Dashboard sidebar
├── ProfileCard.tsx # User profile card
├── StatsCard.tsx # Statistics card
└── ...
Tailwind CSS for utility-first styling:
<button className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
Click Me
</button>Reusable Class Utilities:
// utils/cn.ts
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}-
Install Vercel CLI
npm i -g vercel
-
Build the application
npm run build
-
Deploy
vercel --prod
-
Set Environment Variables
- Go to Vercel Dashboard → Project Settings → Environment Variables
- Add
NEXT_PUBLIC_API_URL
# Build for production
npm run build
# Start production server
npm startDevelopment:
NEXT_PUBLIC_API_URL=http://localhost:5000/apiStaging:
NEXT_PUBLIC_API_URL=https://backend-staging.vercel.app/apiProduction:
NEXT_PUBLIC_API_URL=https://backend-production.vercel.app/api-
Feature-Based Structure
- Group related files by feature, not by type
- Each feature has its own API slice and components
-
Component Composition
- Keep components small and focused
- Use composition over complex component logic
-
TypeScript Everywhere
- Define interfaces for all props
- Use type inference where possible
- Avoid
anytype
-
Code Splitting
const AdminDashboard = dynamic(() => import('@/app/admin/dashboard/page'), { loading: () => <LoadingSpinner /> });
-
Image Optimization
import Image from 'next/image'; <Image src="/banner.jpg" alt="Banner" width={1920} height={1080} priority />
-
Memoization
const MemoizedComponent = React.memo(({ data }) => { return <div>{/* Heavy computation */}</div>; });
-
Input Validation
- Use Zod schemas with React Hook Form
- Sanitize user input
-
XSS Prevention
- Never use
dangerouslySetInnerHTMLwithout sanitization - Use React Quill for rich text (built-in sanitization)
- Never use
-
Token Storage
- Store JWT in HTTP-only cookies (server-side)
- Use secure and sameSite flags
1. API Connection Failed
Error: Network Error
- Verify
NEXT_PUBLIC_API_URLis correct - Check if backend is running
- Ensure CORS is configured on backend
2. Authentication Not Persisting
User logged out on page refresh
- Check if token is being stored in cookies
- Verify token expiry time
- Check browser console for errors
3. Images Not Loading
403 Forbidden on Cloudinary images
- Verify Cloudinary URLs are public
- Check image upload permissions
- Ensure correct image paths
4. Build Errors
Error: Module not found
- Run
npm installto ensure all dependencies are installed - Check import paths (use absolute paths with
@/) - Clear
.nextfolder and rebuild
| Command | Description |
|---|---|
npm run dev |
Start development server at localhost:3000 |
npm run build |
Build for production |
npm start |
Run production build |
npm run lint |
Run ESLint (Next.js built-in) |
This project is licensed under the ISC License.
Lead Developer: Zubayer Hossain Uday
Email: zubayerhossain1009@gmail.com
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Follow existing code style
- Write meaningful commit messages
- Submit a pull request
Built with ❤️ for SUST CSE Department