Template Architecture

A production-ready, full-stack Next.js 16 CMS and portfolio application with admin dashboard, MongoDB backend, JWT authentication, and Cloudinary media management.

Overview

Template Architecture is a comprehensive full-stack web application built with Next.js 16 (App Router), React 19, TypeScript, and MongoDB. It provides a complete admin CMS dashboard for managing content and a public-facing portfolio website for showcasing work.

The application follows modern web development best practices with server components, server actions, API routes organized by feature, role-based access control, and a fully type-safe codebase.

Features

Admin Dashboard

Full CMS with CRUD operations for projects, services, teams, testimonials, collaborations, and more.

Portfolio Website

Responsive public site with hero, about, services, portfolio, testimonials, and contact sections.

JWT Authentication

Secure admin login with 30-day token expiry, bcrypt password hashing, and role-based access control.

Cloudinary Integration

Image and video upload, optimization, and CDN delivery. Configurable from the admin panel.

Dynamic Content

Configurable home page sections, page banners, SEO metadata, business hours, and terms/policy.

Drag & Drop

Sortable lists for teams, testimonials, and services using @dnd-kit for intuitive reordering.

Rich Text Editor

SunEditor integration for creating HTML content in settings, terms, and policy pages.

Data Tables

TanStack React Table with pagination, sorting, search, and status toggle capabilities.

Docker Ready

Production Dockerfile included for containerized deployments with Node 20 and pnpm.

Tech Stack

CategoryTechnology
FrameworkNext.js 16 (App Router)
LanguageTypeScript 5 (Strict Mode)
UI LibraryReact 19
StylingTailwind CSS v4, Radix UI, ShadCN/UI
DatabaseMongoDB with Mongoose ODM
AuthenticationNextAuth v5 (Beta) + JSON Web Tokens
File StorageCloudinary
Form HandlingReact Hook Form + Zod v4
State ManagementZustand
Data TablesTanStack React Table
Drag & Drop@dnd-kit
Rich Text EditorSunEditor
IconsLucide React, React Icons
Date Handlingdate-fns, Moment.js
CachingNode Cache (30-day TTL)
Package Managerpnpm
DeploymentDocker (Node 20)

Prerequisites

  • Node.js v20 or higher
  • pnpm (recommended) or npm
  • MongoDB — A MongoDB Atlas cluster or local instance
  • Cloudinary Account — For image and video uploads

Installation

1. Clone the Repository

git clone <repository-url>
cd template-architecture

2. Install Dependencies

pnpm install

3. Configure Environment Variables

Create a .env file in the project root (see Environment Variables section for details).

4. Run the Development Server

pnpm dev

The application will be available at http://localhost:3000.

5. Build for Production

pnpm build
pnpm start

Environment Variables

Create a .env file in the project root with the following variables:

AUTH_TRUST_HOST="true"
NEXTAUTH_SECRET="your-secret-key-here"
NEXTAUTH_URL="http://localhost:3000"
NEXT_PUBLIC_BASE_URL="http://localhost:3000"
MONGODB_URI="mongodb+srv://<username>:<password>@<cluster>.mongodb.net/<database>?retryWrites=true&w=majority"
VariableRequiredDescription
AUTH_TRUST_HOSTYesSet to "true" for NextAuth in production
NEXTAUTH_SECRETYesSecret key for JWT signing and session encryption
NEXTAUTH_URLYesFull URL of your application
NEXT_PUBLIC_BASE_URLYesPublic base URL used in client-side API calls
MONGODB_URIYesMongoDB connection string
Generate a strong secret with: openssl rand -base64 32

Default Admin Credentials

On first run, the application automatically seeds a default admin account:

FieldValue
Emailadmin@example.com
PasswordChangeMe123!
Login URL/admin/login
Change the default password immediately after your first login via the admin dashboard settings.

Project Structure

template-architecture/
├── app/                              # Next.js App Router
│   ├── (auth)/                       # Auth layout group
│   │   └── admin/login/              # Admin login page
│   ├── (private)/                    # Protected admin routes
│   │   └── admin/dashboard/          # Dashboard & sub-routes
│   │       ├── (showcase)/           # About Us, Our Work, Story
│   │       ├── banner/               # Banner management
│   │       ├── collaborations/       # Collaborations CRUD
│   │       ├── contact-list/         # Contact submissions
│   │       ├── projects/             # Project CRUD (create, edit)
│   │       ├── services/             # Service types management
│   │       ├── settings/             # App settings
│   │       ├── subscribe/            # Newsletter subscribers
│   │       ├── teams/                # Team management
│   │       ├── testimonials/         # Testimonials management
│   │       └── _components/          # Dashboard UI components
│   ├── (public)/                     # Public-facing pages
│   │   ├── about/                    # About page
│   │   ├── contact/                  # Contact form
│   │   ├── portfolio/                # Portfolio grid
│   │   ├── project/[id]/            # Project detail
│   │   ├── policy/                   # Privacy policy
│   │   └── terms/                    # Terms & conditions
│   ├── api/
│   │   ├── admin/                    # Protected API routes
│   │   │   ├── auth/                 # Login, me, password
│   │   │   ├── banner/              # Banner CRUD
│   │   │   ├── collaborations/      # Collaborations CRUD
│   │   │   ├── contact-us/          # Contact management
│   │   │   ├── dashboard/stats/     # Dashboard statistics
│   │   │   ├── file/               # File upload/delete
│   │   │   ├── home-section/       # Home section CRUD
│   │   │   ├── project/            # Project CRUD
│   │   │   ├── service-type/       # Service type CRUD
│   │   │   ├── settings/           # Settings management
│   │   │   ├── subscribe/          # Subscription management
│   │   │   ├── team/               # Team CRUD
│   │   │   ├── testimonial/        # Testimonial CRUD
│   │   │   └── about-section/      # About section CRUD
│   │   ├── auth/[...nextauth]/     # NextAuth configuration
│   │   └── public/                  # Public API routes
│   └── layout.tsx                   # Root layout
├── actions/                          # Server Actions
│   ├── about/                       # About section actions
│   ├── admin/                       # Admin auth actions
│   ├── banner/                      # Banner actions
│   ├── collaborations/              # Collaboration actions
│   ├── contact-list/                # Contact list actions
│   ├── dashboard/                   # Dashboard statistics
│   ├── fileUpload/                  # File upload actions
│   ├── profile/                     # Profile actions
│   ├── projects/                    # Project actions
│   ├── services/                    # Service actions
│   ├── settings/                    # Settings actions
│   ├── showcase/                    # Showcase actions
│   ├── subscribe/                   # Subscribe actions
│   ├── teams/                       # Team actions
│   └── testimonial/                 # Testimonial actions
├── components/                       # React Components
│   ├── custom/                      # Reusable UI components
│   │   ├── data-table/             # DataTable with pagination
│   │   ├── CustomImage.tsx         # Cloudinary image wrapper
│   │   ├── DateTimePicker.tsx      # Date picker component
│   │   ├── RichTextEditor.tsx      # SunEditor wrapper
│   │   ├── img-dropzone-single.tsx # Drag-drop image upload
│   │   ├── PhoneInputField.tsx     # Phone input component
│   │   └── ToasterComponents.tsx   # Toast notifications
│   └── features/landing/           # Landing page components
├── model/                            # Mongoose Schemas
│   ├── User.ts                      # Admin user model
│   ├── Project.ts                   # Project model
│   ├── Team.ts                      # Team member model
│   ├── ServiceType.ts               # Service type model
│   ├── Testimonial.ts               # Testimonial model
│   ├── Banner.ts                    # Banner model
│   ├── ContactUs.ts                 # Contact submission model
│   ├── Subscribe.ts                 # Email subscription model
│   ├── HomeSection.ts               # Home section model
│   ├── AboutSection.ts              # About section model
│   ├── Settings.ts                  # Global settings model
│   └── collaborations.ts            # Collaborations model
├── lib/                              # Utilities & Helpers
│   ├── async-handler.ts             # API route error handler
│   ├── async-formdata-handler.ts    # FormData handler
│   ├── authenticate.ts              # JWT auth middleware
│   ├── api-client.ts                # Server-side API client
│   ├── server-utils.ts              # Cloudinary, JWT, validation
│   ├── validation-schema.ts         # Zod validation schemas
│   ├── mongo-adapter.ts             # MongoDB aggregation helper
│   ├── fileUpload.ts                # File upload utilities
│   ├── file-validator.ts            # File type/size validation
│   ├── compressImages.ts            # Image compression
│   ├── metadata.ts                  # SEO metadata helpers
│   ├── helper-funcs.ts              # General utilities
│   ├── utils.ts                     # Client-side utilities
│   └── types.ts                     # TypeScript definitions
├── config/                           # Configuration
│   ├── database.ts                  # MongoDB connection & seeding
│   ├── cloudinary.ts                # Cloudinary SDK setup
│   ├── routes.ts                    # Route constants
│   ├── constant.ts                  # App constants & enums
│   └── cache.ts                     # Node Cache setup
├── hooks/                            # React Custom Hooks
├── public/                           # Static Assets
├── Dockerfile                        # Docker deployment
├── next.config.ts                    # Next.js configuration
├── tsconfig.json                     # TypeScript configuration
├── components.json                   # ShadCN/UI configuration
└── .env                              # Environment variables

App Routing

The application uses Next.js App Router with route groups to organize pages by access level:

Route GroupPurposeLayout
(auth)Authentication pages (admin login)Minimal layout
(private)Protected admin dashboard pagesDashboard layout with sidebar navigation
(public)Public-facing website pagesPublic layout with header and footer

Public Routes

RouteDescription
/Home / Landing page
/aboutAbout page
/portfolioPortfolio showcase
/project/:slugProject detail page
/contactContact form
/termsTerms & conditions
/policyPrivacy policy

Admin Routes

RouteDescription
/admin/loginAdmin login page
/admin/dashboardDashboard home with statistics
/admin/dashboard/projectsProject management
/admin/dashboard/servicesService type management
/admin/dashboard/teamsTeam member management
/admin/dashboard/testimonialsTestimonial management
/admin/dashboard/collaborationsCollaborations management
/admin/dashboard/bannerBanner management
/admin/dashboard/contact-listContact form submissions
/admin/dashboard/subscribeNewsletter subscribers
/admin/dashboard/settingsApplication settings
/admin/dashboard/about-usAbout us content editor
/admin/dashboard/our-workOur work content editor
/admin/dashboard/storyStory content editor

Authentication

Authentication Flow

  1. Admin submits email and password at /admin/login.
  2. Server validates credentials against the database using bcrypt.
  3. A JWT token is generated (signed with NEXTAUTH_SECRET, 30-day expiry).
  4. Token is stored in the NextAuth session.
  5. All subsequent admin API requests include the token as Authorization: Bearer <token>.
  6. The authenticate() middleware verifies the JWT on every protected endpoint.

JWT Configuration

PropertyValue
AlgorithmHS256
Token Expiry30 days
Payload{ email, role }
Password Hashingbcrypt (10 salt rounds)

Role-Based Access Control

The system supports two roles: admin and user. All admin dashboard and API routes require the admin role. The role is embedded in the JWT payload and verified on each request.

Database Models

All models are defined using Mongoose ODM and stored in the model/ directory. Timestamps (createdAt, updatedAt) are automatically added to all models.

User

FieldTypeDescription
nameStringAdmin name (required)
emailStringUnique email address (required, indexed)
passwordStringBcrypt hashed password
roleEnumadmin or user

Project

FieldTypeDescription
titleStringProject title
slugStringURL-friendly slug
shortDescriptionStringBrief summary
descriptionStringFull HTML description
typeObjectIdReference to ServiceType
thumbnailStringCloudinary image path
imageStringCloudinary image path
isFeaturedBooleanShow in featured section
activeBooleanPublished status
featureArray{ title, description }
galleryArray{ title, image }

Team

FieldTypeDescription
nameStringMember name (required)
designationStringJob title (required)
imageStringCloudinary image path
detailsStringBio or description
positionNumberSort order (default: 0)
statusBooleanActive status (default: true)

ServiceType

FieldTypeDescription
titleStringService name
descriptionStringService description
statusBooleanActive status
positionNumberSort order

Testimonial

FieldTypeDescription
imageStringAuthor photo
quoteStringTestimonial text
authorNameStringAuthor name
authorRoleStringAuthor designation
orderNumberSort order
statusBooleanActive status

Banner

FieldTypeDescription
titleStringBanner title (required)
subTitleStringSubtitle text
descriptionStringBanner description
imagesArrayCloudinary image paths
isPairedBooleanPaired display mode

ContactUs

FieldTypeDescription
nameStringSender name (required)
emailStringSender email (required)
phoneStringPhone number
messageStringMessage content
statusBooleanRead status

HomeSection

FieldTypeDescription
sectionKeyStringUnique section identifier
titleStringSection title
subTitleStringSubtitle
featuresArray{ title, description }
statsArray{ value, suffix, label }
contentMixedFlexible JSON data
sectionTypeStringContent type identifier

AboutSection

FieldTypeDescription
titleStringSection title
philosophyDescriptionStringPhilosophy content (required)
philosophyImageStringPhilosophy image (required)
missionDescriptionStringMission content (required, max 1000)
missionImageStringMission image (required)
visionDescriptionStringVision content (required)
visionImageStringVision image (required)

Settings

FieldTypeDescription
generalObjectCompany name, phone, email, address, logo, favicon, social links
businessHoursArray7-day schedule with open/close times
pageBannerObjectImages for various pages
cloudinaryObjectCloud name, API key, API secret, folder name
metadataObjectSEO title, description, keywords, OG image
termsPolicyObjectTerms and privacy policy HTML content

Collaborations

FieldTypeDescription
nameStringPartner name (required)
imageStringPartner logo
statusBooleanActive status

Middleware & Utilities

asyncHandler

Wraps API route handlers with automatic database connection, JWT authentication (when enabled), Zod request validation, and standardized error handling.

// With validation and auth
export const POST = asyncHandler(createProjectSchema, async (req, data, params) => {
  // data is validated and typed
  return apiResponse(true, 201, 'Created', result);
}, true); // true = require authentication

// Without validation, with auth
export const GET = asyncHandler(async (req, params) => {
  return apiResponse(true, 200, 'Success', data);
}, true);

authenticate

JWT verification middleware that extracts the Bearer token from the Authorization header, verifies its signature, and returns the decoded user data.

validation-schema

Centralized Zod validation schemas for all API inputs including admin login, projects, teams, testimonials, settings, and more. Each schema enforces type safety and business rules.

mongo-adapter

Provides a reusable aggregateWithPagination() method for MongoDB aggregation queries with built-in pagination, sorting, matching, and lookup support.

api-client

Server-side fetch wrapper that automatically includes the JWT token from the NextAuth session, handles errors, and supports both JSON and FormData requests.

Server Utilities

  • uploadImage() — Upload files to Cloudinary
  • cleanupCloudinaryAssets() — Delete uploaded files on error
  • transformCloudinaryPaths() — Convert stored paths to full URLs
  • apiResponse() — Standardized API response builder
  • Custom Zod field helpers: requiredStringField(), optionalStringField(), requiredObjectIdField(), etc.

Server Actions

Server actions in the actions/ directory provide server-side functions for handling mutations from the admin dashboard. They use the api-client utility to make authenticated requests to the API routes.

DirectoryPurpose
actions/admin/Admin authentication (login)
actions/projects/Project CRUD operations
actions/services/Service type management
actions/teams/Team member management
actions/testimonial/Testimonial management
actions/collaborations/Collaboration management
actions/banner/Banner management
actions/contact-list/Contact submission management
actions/subscribe/Newsletter subscription management
actions/settings/Settings management
actions/about/About section management
actions/showcase/Showcase content management
actions/fileUpload/File upload operations
actions/profile/Admin profile management
actions/dashboard/Dashboard statistics

API Overview

All API routes are located in app/api/ and follow RESTful conventions. The API is divided into two main groups:

  • Admin API (/api/admin/*) — Protected endpoints that require a valid JWT token
  • Public API (/api/public/*) — Open endpoints for the public website

Response Format

{
  "status": true,
  "message": "Success message",
  "data": { },
  "pagination": {
    "totalDocs": 100,
    "page": 1,
    "limit": 10,
    "pages": 10,
    "hasNext": true,
    "hasPrev": false
  }
}

Query Parameters (Paginated Endpoints)

ParameterTypeDefaultDescription
pagenumber1Page number
limitnumber10Items per page
searchstringSearch keyword (case-insensitive)
sortBystringcreatedAtField to sort by
sortOrderstringdescSort direction (asc/desc)

Authentication Header

Authorization: Bearer <jwt-token>

Authentication API

MethodEndpointDescription
POST/api/admin/auth/loginLogin with email and password
GET/api/admin/auth/meGet current admin profile
POST/api/admin/auth/passwordChange password

POST /api/admin/auth/login

// Request Body
{
  "email": "admin@example.com",
  "password": "ChangeMe123!"
}

// Response
{
  "status": true,
  "message": "Login successful",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "user": { "name": "Admin", "email": "admin@example.com", "role": "admin" }
  }
}

Projects API

Admin Endpoints

MethodEndpointDescription
GET/api/admin/projectList projects (paginated, searchable)
POST/api/admin/projectCreate a new project
GET/api/admin/project/:idGet project by ID
PUT/api/admin/project/:idUpdate project
DELETE/api/admin/project/:idDelete project

Public Endpoints

MethodEndpointDescription
GET/api/public/projectList active projects (paginated, filterable)
GET/api/public/project/:slugGet project by slug
GET/api/public/project/featureGet featured projects

Service Types API

MethodEndpointDescription
GET/api/admin/service-typeList service types
POST/api/admin/service-typeCreate service type
PUT/api/admin/service-type/:idUpdate service type
DELETE/api/admin/service-type/:idDelete service type
POST/api/admin/service-type/sortReorder services

Public: GET /api/public/service-type — List active services

Teams API

MethodEndpointDescription
GET/api/admin/teamList team members
POST/api/admin/teamCreate team member
PUT/api/admin/team/:idUpdate team member
DELETE/api/admin/team/:idDelete team member
POST/api/admin/team/sortReorder team members
PATCH/api/admin/team/status/:idToggle team member status

Public: GET /api/public/team — List active team members

Testimonials API

MethodEndpointDescription
GET/api/admin/testimonialList testimonials
POST/api/admin/testimonialCreate testimonial
PUT/api/admin/testimonial/:idUpdate testimonial
DELETE/api/admin/testimonial/:idDelete testimonial
POST/api/admin/testimonial/sortReorder testimonials
PATCH/api/admin/testimonial/status/:idToggle status

Public: GET /api/public/testimonial — List active testimonials

Collaborations API

MethodEndpointDescription
GET/api/admin/collaborationsList collaborations
POST/api/admin/collaborationsCreate collaboration
PUT/api/admin/collaborations/:idUpdate collaboration
DELETE/api/admin/collaborations/:idDelete collaboration
PATCH/api/admin/collaborations/status/:idToggle status

Public: GET /api/public/collaborations — List active collaborations

Contact API

Admin Endpoints

MethodEndpointDescription
GET/api/admin/contact-usList contact submissions (paginated)
PUT/api/admin/contact-us/:idUpdate submission status
DELETE/api/admin/contact-us/:idDelete submission

Public Endpoint

MethodEndpointDescription
POST/api/public/contact-usSubmit contact form

Banner API

MethodEndpointDescription
GET/api/admin/bannerGet banner
POST/api/admin/bannerCreate or update banner
PUT/api/admin/bannerUpdate banner

Public: GET /api/public/banner — Get banner content

Home Sections API

MethodEndpointDescription
GET/api/admin/home-sectionList home sections
POST/api/admin/home-sectionCreate home section
PUT/api/admin/home-sectionUpdate home section
GET/api/admin/home-section/name/:slugGet section by slug
PUT/api/admin/home-section/name/:slugUpdate section by slug
DELETE/api/admin/home-section/name/:slugDelete section by slug

Public: GET /api/public/home-section and GET /api/public/home-section/:slug

About Section API

MethodEndpointDescription
GET/api/admin/about-sectionGet about section
POST/api/admin/about-sectionCreate or update about section

Public: GET /api/public/about-section — Get about section content

Settings API

MethodEndpointDescription
GET/api/admin/settingsGet all settings
POST/api/admin/settings/generalUpdate general settings
POST/api/admin/settings/cloudinaryUpdate Cloudinary config
POST/api/admin/settings/metadataUpdate SEO metadata
POST/api/admin/settings/business-hourUpdate business hours
POST/api/admin/settings/page-bannerUpdate page banners
POST/api/admin/settings/termsUpdate terms & policy

Public: GET /api/public/settings — Get public settings

File Upload API

MethodEndpointDescription
POST/api/admin/fileUpload image(s) to Cloudinary
DELETE/api/admin/fileDelete image(s) from Cloudinary

File uploads use multipart/form-data. Supported formats include JPEG, PNG, WebP, SVG, and video files. Maximum upload size is 50MB (configurable in next.config.ts).

Dashboard API

MethodEndpointDescription
GET/api/admin/dashboard/statsGet dashboard statistics

Returns counts and summaries of all content types for the admin dashboard overview.

Newsletter API

Admin Endpoints

MethodEndpointDescription
GET/api/admin/subscribeList subscribers (paginated)
DELETE/api/admin/subscribe/:idDelete subscriber

Public Endpoint

MethodEndpointDescription
POST/api/public/subscribeSubscribe to newsletter

Public Endpoints Summary

All public endpoints are accessible without authentication.

MethodEndpointDescription
GET/api/public/projectList active projects
GET/api/public/project/:slugGet project by slug
GET/api/public/project/featureGet featured projects
GET/api/public/service-typeList active services
GET/api/public/teamList active team members
GET/api/public/testimonialList active testimonials
GET/api/public/collaborationsList active collaborations
GET/api/public/bannerGet banner content
GET/api/public/home-sectionList home sections
GET/api/public/home-section/:slugGet section by slug
GET/api/public/about-sectionGet about section
GET/api/public/settingsGet public settings
POST/api/public/contact-usSubmit contact form
POST/api/public/subscribeSubscribe to newsletter

Cloudinary Setup

  1. Create a free account at cloudinary.com.
  2. From your Cloudinary dashboard, note your Cloud Name, API Key, and API Secret.
  3. Log into the admin panel and go to Settings → Cloudinary.
  4. Enter your Cloudinary credentials and set a Folder Name to organize uploads.
Images are stored as Cloudinary public IDs in the database and automatically transformed to full CDN URLs when retrieved.

Settings Management

The admin dashboard provides a comprehensive settings panel with the following tabs:

TabDescription
GeneralCompany name, phone, email, address, logo, favicon, social media links, home view configuration
CloudinaryCloud name, API key, API secret, folder name, secure URL base
MetadataSEO title, application name, description, keywords, Open Graph image
Business Hours7-day weekly schedule with open/close times and closure support
Page BannersBanner images for various pages
Terms & PolicyTerms of service and privacy policy HTML content (Rich Text Editor)

SEO & Metadata

The application generates dynamic metadata for each page using the settings configured in the admin panel. The lib/metadata.ts helper generates page-specific metadata with:

  • Dynamic page titles
  • Meta descriptions
  • Keywords
  • Open Graph images
  • Application name

Configure these values from Admin Dashboard → Settings → Metadata.

Docker Deployment

# Build the image
docker build -t template-architecture .

# Run the container
docker run -p 3000:3000 --env-file .env template-architecture

The Dockerfile uses Node 20 with pnpm, installs dependencies, builds the Next.js application, and exposes port 3000.

Dockerfile Overview

FROM node:20
WORKDIR /app
RUN corepack enable
RUN corepack prepare pnpm@latest --activate
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . .
EXPOSE 3000
RUN pnpm build
CMD ["pnpm", "start"]

Scripts

CommandDescription
pnpm devStart development server on port 3000
pnpm buildBuild for production
pnpm startStart production server
pnpm lintRun ESLint
pnpm docsStart documentation server
pnpm dev:allRun dev server and docs concurrently

Template Architecture v0.1.0 — Built with Next.js 16, React 19, TypeScript & MongoDB

Documentation — Template Architecture