Initializing
Back to Projects
Year2024
DomainFullstack
AccessOpen Source
Complexity0 / 10
Next.jsPostgreSQLPrismaDockerTraefikMinIOGovernmentCMS
FullstackProduction

Pathsala Municipal Board - Official Municipal Portal

A production-grade municipal government website providing citizens 24/7 access to information, services, and governance transparency through a modern Next.js 16 portal with full admin content management.

Parsing system architecture diagram...

Technology Stack

LayerTechnologyVersion/Details
FrameworkNext.js (App Router)16.1.6
RuntimeNode.js22 LTS
LanguageTypeScript5.x
DatabasePostgreSQL16 Alpine
ORMPrisma5.22.0
AuthenticationAuth.js v5^5.0.0-beta.25
Object StorageMinIO (S3-compatible)latest
S3 Client@aws-sdk/client-s3^3.995.0
Image ProcessingSharp^0.34.5
StylingTailwind CSS4.x
DeploymentDocker, Traefiklatest

Purpose and Philosophy

The Pathsala Municipal Board official portal serves as the digital gateway for citizens of Pathsala town to access municipal information, services, and governance transparency. The platform embodies the principle that government information should be accessible 24/7, anywhere, through a modern, responsive interface.

The project follows a modular monolith pattern built on Next.js App Router. Rather than splitting into microservices, all concerns—public citizen-facing pages, administrative dashboard, and REST-style API routes—are co-located in a single deployable container. This approach simplifies deployment, reduces infrastructure complexity, and maintains transaction consistency while still enabling independent scaling if needed later.

Core Design Principles

  1. Citizen-First Accessibility: The public-facing pages require no authentication, load fast on mobile devices, and provide clear navigation to essential information like news, services, board members, and contact details.
  1. Role-Based Content Management: The admin dashboard is protected by Auth.js credentials with role-based access. All content changes are logged for audit purposes, ensuring accountability in governance.
  1. Media-Rich Content: The system supports image galleries, video content, and document uploads through MinIO object storage, enabling the municipality to showcase projects, events, and important notices visually.
  1. Security by Design: The application fails at startup if MinIO credentials are not properly configured. This prevents silent misconfiguration that could lead to data loss or exposure.
  1. Single Source of Truth: All data models are defined in Prisma schema, serving as the definitive source for database structures and enabling type-safe queries throughout the application.

Architecture Deep Dive

Project Structure

code
pathsala-municipal-board/
├── prisma/
│   ├── schema.prisma          # Database models (8 models, 3 domains)
│   └── seed.ts                # Initial admin user seeding
├── scripts/
│   ├── audit-urls.cjs         # Audit MinIO URLs in database
│   └── fix-urls.cjs           # Migrate legacy MinIO URLs
├── src/
│   ├── app/
│   │   ├── (public)/          # Citizen-facing pages (no auth)
│   │   │   ├── page.tsx       # Home page
│   │   │   ├── about/         # About the municipality
│   │   │   ├── administration/ # Governance & board members
│   │   │   ├── contact/       # Contact form
│   │   │   ├── gallery/       # Photo & video gallery
│   │   │   ├── news/          # News and public notices
│   │   │   ├── resources/     # Important links & documents
│   │   │   └── services/      # Municipal services info
│   │   ├── admin/
│   │   │   ├── login/         # Authentication page
│   │   │   └── (protected)/   # Admin dashboard
│   │   │       ├── dashboard/ # Overview & stats
│   │   │       ├── news/      # News management
│   │   │       ├── projects/  # Projects & tenders
│   │   │       ├── members/   # Board member management
│   │   │       ├── gallery/   # Media library
│   │   │       ├── links/     # Important links
│   │   │       ├── messages/  # Contact submissions
│   │   │       ├── storage/   # MinIO diagnostics
│   │   │       └── logs/      # Audit logs
│   │   └── api/
│   │       ├── auth/          # Auth.js handlers
│   │       ├── upload/        # File upload (S3 presigned)
│   │       └── media/         # Media library API
│   ├── components/            # Shared React components
│   ├── lib/
│   │   ├── minio.ts           # S3 client & utilities
│   │   ├── prisma.ts          # Prisma client singleton
│   │   └── audit.ts           # Audit logging action
│   ├── auth.ts                # Auth.js configuration
│   └── auth.config.ts         # Route protection
├── docker-compose.yml         # Full stack orchestration
├── Dockerfile                 # Multi-stage build
└── deploy.sh                 # Zero-downtime deploy

Database Schema

The Prisma schema defines 8 models across 3 distinct domains:

prisma
// Identity Domain
model User {
  id        String   @id @default(cuid())
  email     String   @unique
  password  String
  role      String   @default("ADMIN")
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  AuditLog  AuditLog[]
}

// Content Domain
model Project {
  id          String   @id @default(cuid())
  name        String
  description String
  category    String   @default("PROJECT") // PROJECT / TENDER / DOCUMENT
  fileUrl     String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model News {
  id          String   @id @default(cuid())
  title       String
  description String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

model GalleryItem {
  id        String   @id @default(cuid())
  title     String?
  mediaUrl  String
  type      String   // IMAGE / VIDEO / YOUTUBE
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model ImportantLink {
  id        String   @id @default(cuid())
  name      String
  icon      String?
  url       String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

// Citizen Engagement Domain
model Member {
  id             String   @id @default(cuid())
  name           String
  designation    String
  bio            String?
  profilePicture String?
  email          String?
  contactNumber  String?
  category       String   // Board / Executive Officers / Staff
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt
}

model ContactMessage {
  id        String   @id @default(cuid())
  name      String
  email     String
  phone     String?
  message   String
  createdAt DateTime @default(now())
}

// Governance Domain
model AuditLog {
  id             String   @id @default(cuid())
  userId         String?
  user           User?    @relation(fields: [userId], references: [id])
  actionType     String   // CREATE / UPDATE / DELETE
  entityName     String
  entityId       String?
  changeMetadata String?  // JSON string of diff
  timestamp      DateTime @default(now())
}

Authentication System

The platform uses Auth.js v5 (formerly NextAuth) with a credentials provider:

typescript
// src/auth.ts
export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    Credentials({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        // Validate against database
      },
    }),
  ],
  callbacks: {
    async jwt({ token, user }) {
      // Add role to token
    },
    async session({ session, token }) {
      // Add role to session
    },
  },
  pages: {
    signIn: "/admin/login",
  },
});

All protected admin routes use middleware-based authentication:

typescript
// src/auth.config.ts
export const { auth } = NextAuth(authConfig);

export default authMiddleware;

export const config = {
  matcher: ["/admin/:path*"],
};

Key Features and Functionality

1. Public Citizen Portal

The public-facing pages provide comprehensive municipal information:

Home Page (/)

  • Hero section with municipal branding
  • Quick access to important links
  • Latest news and updates
  • Service highlights

About Section (/about)

  • Municipal history and vision
  • Governance structure
  • Contact information

Administration (/administration)

  • Board members listing with profiles
  • Executive officers and staff directory
  • Organizational hierarchy

News (/news)

  • Public notices and announcements
  • News articles with descriptions
  • Chronological ordering

Gallery (/gallery)

  • Image galleries with lightbox
  • Video content support
  • YouTube embed integration
  • Category-based organization

Services (/services)

  • Municipal service information
  • Online service requests (future)
  • Service guides and procedures

Resources (/resources)

  • Important links to external government portals
  • Downloadable documents
  • Tenders and project notices

Contact (/contact)

  • Contact form for citizen inquiries
  • Telegram bot notifications for admins
  • Stored in database for response tracking

2. Admin Dashboard

Protected routes at /admin/* provide complete content management:

Dashboard (/admin/dashboard)

  • Overview statistics
  • Recent contact messages
  • Quick actions

News Management (/admin/news)

  • Create, edit, delete news articles
  • Rich text descriptions
  • Publication timestamps

Projects & Tenders (/admin/projects)

  • Manage municipal projects
  • Tender notices
  • Document uploads
  • Category classification (PROJECT/TENDER/DOCUMENT)

Board Members (/admin/members)

  • CRUD for board members
  • Profile pictures (MinIO storage)
  • Designation and bio
  • Contact information
  • Category (Board/Executive Officers/Staff)

Gallery Management (/admin/gallery)

  • Upload images and videos
  • YouTube video embedding
  • Title and description
  • Delete functionality

Important Links (/admin/links)

  • Manage external resource links
  • Custom icons
  • URL configuration

Contact Messages (/admin/messages)

  • View all citizen submissions
  • Mark as read/archived
  • Reply tracking

Storage Diagnostics (/admin/storage)

  • MinIO bucket status
  • Storage usage metrics
  • Connection health checks

Audit Logs (/admin/logs)

  • Complete action history
  • User attribution
  • Change metadata (JSON diffs)
  • Timestamp tracking

3. Media Storage System

MinIO provides S3-compatible object storage for all media:

typescript
// src/lib/minio.ts
import { S3Client, PutObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const s3Client = new S3Client({
  endpoint: process.env.MINIO_ENDPOINT,
  credentials: {
    accessKeyId: process.env.MINIO_ROOT_USER,
    secretAccessKey: process.env.MINIO_ROOT_PASSWORD,
  },
  forcePathStyle: true,
});

Upload Flow:

  1. Admin selects file in dashboard
  2. Server generates presigned URL
  3. Browser uploads directly to MinIO
  4. URL stored in database

Storage Buckets:

  • pathsala-media - Main media storage
  • Anonymous download access enabled
  • Public URL delivery via path or subdomain

4. Deployment Infrastructure

Docker Compose orchestrates four services:

yaml
services:
  web:
    image: pathsala-mb-website
    ports: 3000
    networks: [traefik-public, internal-network]
    Traefik: ws.bajali.in

  db:
    image: postgres:16-alpine
    internal-network only

  minio:
    image: minio/minio
    networks: [traefik-public, internal-network]
    Traefik: pmb-media-api.bajali.in, pmb-media-admin.bajali.in

  minio-init:
    image: minio/mc
    One-shot bucket initialization

Traefik Routing:

  • ws.bajali.in → Next.js application
  • pmb-media-api.bajali.in → MinIO S3 API
  • pmb-media-admin.bajali.in → MinIO console
  • ws.bajali.in/pathsala-media/* → MinIO via path prefix

Security Implementation

Authentication & Authorization

  • Auth.js v5 with credentials provider
  • Bcrypt password hashing
  • Session-based authentication with secure cookies
  • Role-based route protection (ADMIN role required for dashboard)

Infrastructure Security

  • Database isolated on internal network (no external access)
  • MinIO credentials validated at startup
  • Environment variables for all secrets
  • External Traefik network for public access only
  • HTTPS enforced via Let's Encrypt

Audit Logging

  • All admin actions logged to AuditLog table
  • JSON change metadata for diff tracking
  • User attribution on all actions
  • Retention for governance accountability

Development and Operations

Local Development

bash
# Full stack with Docker
docker compose up -d

# Native Node.js development
npm install
npm run db:generate
npm run db:migrate
npm run db:seed
npm run dev

Database Scripts

bash
npm run db:migrate     # Create new migration
npm run db:seed        # Seed initial admin
npm run db:studio      # Visual database browser
npm run db:push        # Push schema changes

Production Deployment

The deploy.sh script provides automated deployment:

bash
./deploy.sh --auto    # Non-interactive: commit, push, rsync, rebuild

Monitoring

bash
# View application logs
docker logs -f pathsala-mb-website

# Check database
docker exec -it pathsala-db psql -U postgres -d pathsala_db

# MinIO health
curl https://pmb-media-api.bajali.in/minio/health/live

Production URLs

ServiceURL
Portalhttps://ws.bajali.in
MinIO APIhttps://pmb-media-api.bajali.in
MinIO Consolehttps://pmb-media-admin.bajali.in

Lessons Learned and Best Practices

What Worked Well

  1. Modular Monolith: Single deployable unit simplifies operations while maintaining clear code organization
  2. Prisma Schema as Source of Truth: Type-safe database access throughout the application
  3. MinIO for Media: S3-compatible storage provides scalability without vendor lock-in
  4. Auth.js v5: Modern authentication with session management
  5. Audit Logging: Complete accountability for admin actions

Areas for Enhancement

  1. CI/CD Pipeline: Could implement GitHub Actions for automated testing and deployment
  2. Performance Monitoring: Add application performance monitoring (APM)
  3. Media Optimization: Automatic image resizing and format conversion
  4. Offline Support: Service worker for offline page viewing

Future Expansion

The architecture supports:

  • Online Service Requests: Citizen portal for service applications
  • Payment Integration: Online fee and tax collection
  • Mobile Apps: React Native wrapper using same API
  • Document Management: Version-controlled document repository

Conclusion

The Pathsala Municipal Board portal demonstrates a production-grade implementation of a government website using modern web technologies. The platform successfully provides citizens with 24/7 access to municipal information while giving administrators powerful content management tools.

The modular monolith architecture on Next.js 16 provides the right balance of simplicity and functionality for a municipal portal. With PostgreSQL for data persistence, MinIO for media storage, and comprehensive admin capabilities, the platform serves as a reliable digital infrastructure for local governance transparency.

Architecture Feedback

Spotted a potential optimization or antipattern? Let me know.

Submit a Technical Suggestion