Template Newspaper

A production-ready, full-stack newspaper & news publishing system built with Next.js 16, React 19, MongoDB, and Cloudinary. Ships with a polished public news portal, an admin dashboard, and an author workflow — all out of the box.

📅 Version 1.0.0 🏗️ Next.js 16 + React 19 🗄️ MongoDB + Mongoose ☁️ Cloudinary

Overview

Template Newspaper is a complete news publishing platform that covers every layer of a modern media website. It ships with everything you need out of the box:

Features

Public Portal

Two Homepage Layouts
Classic and Modern layout variants, switchable from admin settings without a rebuild.
Category Pages
Dynamic category and subcategory pages with pagination and subcategory navigation.
Breaking & Latest News
Dedicated breaking news ticker, latest news feed, featured, and most-viewed sections.
News Detail Pages
Full article pages with estimated read time, author info, and social sharing buttons.
Newsletter & Contact
Built-in newsletter subscription form and contact form with admin reply tracking.
SEO Ready
Configurable metadata, Open Graph image, keywords, and page titles from the admin panel.
Dark Mode
Full dark mode support powered by next-themes, with smooth transitions and system detection.
Auto Sitemap
Automatically generated sitemap and legal pages (Privacy Policy, Terms & Conditions, About Us).

Admin Dashboard

News Management
Create, edit, publish, reject, sort, and soft-delete articles. Full status workflow control.
Category Management
Hierarchical categories and subcategories with drag-and-drop reordering (dnd-kit).
Author Management
Create and manage author accounts. Activate, deactivate, and delete authors.
Contact & Newsletter
View contact submissions with replied status, and browse newsletter subscriber list.
Settings Panel
Configure general info, Cloudinary credentials, SEO metadata, and legal page content.
Dashboard Statistics
At-a-glance stats: total news, authors, contacts, subscribers, and interactive charts.

Author Dashboard

Rich Text Editor
Full article creation powered by SunEditor — a feature-rich WYSIWYG HTML editor.
Review Workflow
Authors submit articles for admin review. Track status: Draft → Under Review → Published / Rejected.

Technology Stack

Next.js 16 App Router, Server Components, Turbopack
React 19 Latest stable release
TypeScript 5 Strict type safety throughout
MongoDB 6+ via Mongoose 8 ODM
NextAuth v5 Session + JWT Credentials provider
Tailwind CSS v4 Utility-first styling
Radix UI + shadcn Accessible UI primitives
SunEditor Rich text / WYSIWYG editor
React Hook Form Performant forms
Zod Schema-first validation
TanStack Table Headless data tables
dnd-kit Drag-and-drop sorting
Cloudinary Media storage & delivery
Zustand Lightweight state management
Recharts Dashboard charts
Lucide + Tabler Icons Modern SVG icon sets
React Hot Toast Toast notifications
Embla Carousel Smooth carousels

Requirements

RequirementMinimum VersionNotes
Node.js18.18 or laterLTS recommended
npm9.x or laterpnpm / yarn / bun also supported
MongoDB6.0 or laterLocal or MongoDB Atlas (free tier)
Cloudinary AccountAnyFree tier is sufficient

Installation & Setup

Step 1 — Extract Files
unzip template-newspaper.zip -d template-newspaper
cd template-newspaper
Step 2 — Install Dependencies
npm install
Step 3 — Configure Environment Variables
cp .env.example .env
# Then edit .env with your actual values

See the Environment Variables section for all required values.

Step 4 — Create the First Admin Account

Insert an admin user document directly into MongoDB (via MongoDB Compass or Atlas UI). Set role to "admin" and use a bcrypt-hashed password.

Step 5 — Start Development Server
npm run dev

Open http://localhost:3000 in your browser. The admin dashboard is at http://localhost:3000/admin/dashboard. The interactive documentation is at http://localhost:3000/documentation.

Environment Variables

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

# ─── Database ──────────────────────────────────────────────────────
# MongoDB connection string (Atlas or local instance)
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/<db>

# ─── Authentication ────────────────────────────────────────────────
# Long random string for signing JWTs. Generate: openssl rand -base64 32
NEXTAUTH_SECRET=your-secret-key-here

# ─── Internal API URL ──────────────────────────────────────────────
# Use http://localhost:3000 for local dev; production domain in prod
NEXT_API_URL=http://localhost:3000

# ─── Cloudinary ────────────────────────────────────────────────────
# Can also be configured via Admin → Settings → Cloudinary
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
ℹ️ Cloudinary Credentials
The CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, and CLOUDINARY_API_SECRET are also manageable through Admin Dashboard → Settings → Cloudinary (saved in the database). Changes take effect without redeploying.
⚠️ Security Notice
Never commit .env to version control. It is listed in .gitignore by default. Always set a strong, unique NEXTAUTH_SECRET in production.

Running the Application

CommandDescription
npm run devStart development server with Turbopack at localhost:3000
npm run buildCreate an optimised production build
npm run startServe the production build
npm run lintRun ESLint code quality checks

Project Structure

template-newspapper/
├── public/
│   ├── documentation.html           # Standalone HTML documentation
│   └── documentation-pdf.html       # Print-optimised documentation
│
├── src/
│   ├── app/                         # Next.js App Router root
│   │   ├── (auth)/                  # Auth pages (no header/footer)
│   │   │   └── login/
│   │   │
│   │   ├── (public)/                # Public-facing pages
│   │   │   ├── layout.tsx           # Header + Footer wrapper
│   │   │   ├── page.tsx             # Homepage (classic / modern)
│   │   │   ├── [category]/          # Category listing pages
│   │   │   ├── news/[slug]/         # News detail page
│   │   │   ├── about-us/
│   │   │   ├── contact-us/
│   │   │   ├── privacy-policy/
│   │   │   ├── terms-and-conditions/
│   │   │   └── site-map/
│   │   │
│   │   ├── (dashboard)/             # Protected dashboard (auth required)
│   │   │   ├── layout.tsx           # Sidebar shell
│   │   │   ├── admin/
│   │   │   │   ├── dashboard/       # Stats & charts
│   │   │   │   ├── news/            # News CRUD & status management
│   │   │   │   ├── categories/      # Category & subcategory management
│   │   │   │   ├── authors/         # Author account management
│   │   │   │   ├── contacts/        # Contact submissions
│   │   │   │   ├── newsletters/     # Newsletter subscribers
│   │   │   │   └── settings/        # Site-wide settings
│   │   │   └── author/
│   │   │       ├── dashboard/       # Author personal stats
│   │   │       └── news/            # Author's own articles
│   │   │
│   │   ├── documentation/           # /documentation route
│   │   │
│   │   └── api/
│   │       ├── auth/[...nextauth]/  # NextAuth handler
│   │       ├── admin/               # All admin API endpoints
│   │       ├── author/              # Author API endpoints
│   │       └── landing/             # Public API endpoints
│   │
│   ├── components/
│   │   ├── ui/                      # shadcn/ui primitives (50+ components)
│   │   ├── form/                    # Reusable form field components
│   │   ├── shared/                  # Header, Footer, layout components
│   │   ├── dashboard/               # Dashboard-specific widgets
│   │   └── data-table/              # TanStack React Table components
│   │
│   ├── lib/
│   │   ├── async-handler.ts         # API route wrapper (auth + validation)
│   │   ├── authenticate.ts          # JWT verification middleware
│   │   ├── fetcher.ts               # Authenticated HTTP client
│   │   ├── routes.ts                # Centralised route constants
│   │   ├── utils.ts                 # Helpers (cn, slugify, paginate…)
│   │   └── validation-schema.ts     # Zod schemas for all entities
│   │
│   ├── model/
│   │   ├── User.ts
│   │   ├── News.ts
│   │   ├── Category.ts
│   │   ├── Contact.ts
│   │   ├── Newsletter.ts
│   │   └── Settings.ts
│   │
│   ├── services/                    # Business logic / server actions
│   │   └── auth.ts / news.ts / categories.ts / authors.ts / …
│   │
│   ├── config/
│   │   ├── database.ts              # MongoDB connection singleton
│   │   ├── cloudinary.ts            # Cloudinary SDK setup
│   │   └── constant.ts              # App-wide constants (roles, statuses)
│   │
│   ├── hooks/
│   │   ├── use-user.ts
│   │   └── use-mobile.ts
│   │
│   └── store/                       # Zustand client state stores
│       ├── user-store.ts
│       ├── breadcrumb-store.ts
│       ├── category-store.tsx
│       └── table-store.ts
│
├── .env / .env.example
├── next.config.ts
├── tailwind.config.ts
├── tsconfig.json
├── components.json                  # shadcn/ui config
└── package.json

Pages & Routes

Public Pages

RouteDescription
/Homepage — Classic or Modern layout (configured in settings)
/[category]Category listing page with subcategory navigation and pagination
/news/[slug]Full news article detail page
/about-usAbout Us page (content editable from admin)
/contact-usContact form page
/privacy-policyPrivacy Policy page (content editable from admin)
/terms-and-conditionsTerms & Conditions page (content editable from admin)
/site-mapAuto-generated sitemap
/loginLogin page for admin and author accounts
/documentationBuilt-in interactive documentation

Admin Dashboard Pages (Protected)

All admin routes are under /admin/ and require a valid admin authentication session.

RouteDescription
/admin/dashboardOverview statistics and charts
/admin/newsNews list with filters and status management
/admin/news/createCreate new article
/admin/news/[slug]Edit existing article
/admin/categoriesCategory list with drag-to-reorder
/admin/categories/createCreate new category
/admin/categories/[slug]Edit category & subcategories
/admin/authorsAuthor account management
/admin/contactsContact form submissions
/admin/newslettersNewsletter subscriber list
/admin/settings/generalGeneral site settings
/admin/settings/cloudinaryCloudinary credentials
/admin/settings/metadataSEO metadata settings
/admin/settings/terms-and-conditionsTerms page content
/admin/settings/privacy-policyPrivacy policy content
/admin/settings/about-usAbout Us page content

Author Dashboard Pages (Protected)

All author routes are under /author/ and require a valid author session.

RouteDescription
/author/dashboardAuthor personal statistics
/author/newsAuthor's own article list
/author/news/createCreate new article
/author/news/[slug]Edit own article

Roles & Permissions

RoleAccess
adminFull access to admin dashboard, all content, settings, and user management
authorAccess to author dashboard; can create, edit, and submit own articles only
userReserved for future public-user features; no dashboard access currently

Route protection is enforced at middleware level — unauthenticated requests to dashboard routes are redirected to /login.

Authentication

Authentication is powered by NextAuth v5 with the Credentials provider and JWT sessions (30-day expiry).

Login Flow

  1. User submits email and password on /login.
  2. The credentials provider calls the backend login endpoint for the appropriate role.
  3. Backend verifies the password with bcrypt and issues a signed JWT.
  4. NextAuth stores the token in a secure, HTTP-only session cookie.
  5. API requests include the token as Authorization: Bearer <token>.
  6. The authenticate() middleware verifies the token and attaches the user to the request context.

Key Files

FilePurpose
src/app/api/auth/[...nextauth]/auth.tsNextAuth configuration and callbacks
src/lib/authenticate.tsJWT verification middleware for API routes
src/lib/async-handler.tsAPI route wrapper with role-checking and Zod validation
src/hooks/use-user.tsReact hook to read the current authenticated user

API Reference — Public Endpoints

All API responses follow a consistent envelope format:

// Success
{ "success": true, "statusCode": 200, "message": "...", "data": { ... } }

// Error
{ "success": false, "statusCode": 400, "message": "...", "errors": [ ... ] }

News & Categories

GET/api/landing/news-category
Returns all active categories for the public navigation header.
GET/api/landing/news/[slug]
Returns a single published news article by its unique slug. Increments view count.
GET/api/landing/latest-news
Returns the most recently published articles flagged as latest.
GET/api/landing/breaking-news
Returns articles flagged as breaking news for the ticker.
GET/api/landing/category-wise-news/[categoryId]/[subcategoryId]
Returns paginated published articles for the given category and subcategory.
Query Parameters: page (default: 1), limit (default: 10)
GET/api/landing/category-wise-news/[categoryId]/[subcategoryId]/featured
Returns featured articles within a specific category.
GET/api/landing/category-wise-news/[categoryId]/[subcategoryId]/most-viewed
Returns most-viewed articles within a specific category, sorted by viewCount.

Contact, Newsletter & Settings

POST/api/landing/contact
Submits a contact form enquiry.
{ "name": "Jane Doe", "email": "jane@example.com", "message": "Hello!" }
POST/api/landing/newsletter
Subscribes an email address to the newsletter.
{ "email": "reader@example.com" }
GET/api/landing/settings
Returns public site settings (company name, logo, social links, home view preference).

API Reference — Authentication

ℹ️ Protected Endpoints
All admin and author management endpoints require: Authorization: Bearer <token>
POST/api/admin/auth/login
Authenticates an admin user and returns a JWT token.
// Request
{ "email": "admin@example.com", "password": "your_password" }

// Response
{
  "success": true,
  "data": {
    "token": "eyJhbGci...",
    "user": { "name": "Admin", "email": "admin@example.com", "role": "admin" }
  }
}
POST/api/author/auth/login
Authenticates an author user and returns a JWT token.
GET/api/admin/auth/me
Returns the currently authenticated admin's profile. Requires Bearer token.
PUT/api/admin/auth/me
Updates the admin's profile name. Requires Bearer token.
PUT/api/admin/auth/password
Changes the admin password. Requires Bearer token.
{ "oldPassword": "current", "newPassword": "new_pass", "confirmPassword": "new_pass" }
GET/api/author/auth/me
Returns the current author's profile. Requires Bearer token.
PUT/api/author/auth/me
Updates the author's profile. Requires Bearer token.
PUT/api/author/auth/password
Changes the author's password. Requires Bearer token.

API Reference — Categories

MethodEndpointDescription
GET/api/admin/categoryList all categories with subcategories
POST/api/admin/categoryCreate a new category
GET/api/admin/category/[slug]Get single category with its subcategories
PUT/api/admin/category/[slug]Update category details and subcategories
DELETE/api/admin/category/[slug]Delete category and its subcategories
PUT/api/admin/category/sortReorder categories (drag-and-drop)
// Create Category — Request Body
{
  "name": "Politics",
  "slug": "politics",
  "status": true,
  "featured": true,
  "subCategories": [
    { "name": "National", "slug": "national", "status": true }
  ]
}

API Reference — Authors

MethodEndpointDescription
GET/api/admin/authorList all author accounts
POST/api/admin/authorCreate a new author account
PUT/api/admin/author/[id]Update author details or status
DELETE/api/admin/author/[id]Delete an author account
// Create Author — Request Body
{
  "name": "Jane Reporter",
  "email": "jane@newsroom.com",
  "password": "initial_password"
}

API Reference — News (Admin)

MethodEndpointDescription
GET/api/admin/newsPaginated news list with status, category, and author filters
POST/api/admin/newsCreate and publish a news article (with image upload)
GET/api/admin/news/[slug]Get a single article
PUT/api/admin/news/[slug]Update article content, status, or flags
DELETE/api/admin/news/[slug]Soft-delete article (recoverable)
PUT/api/admin/news/sortReorder articles by position
PUT/api/admin/news/reject/[slug]Reject a submitted article with a reason
// News article status values
"draft"      // saved but not submitted
"review"     // submitted by author, awaiting admin action
"published"  // live on the public portal
"rejected"   // rejected by admin with a reason

// Reject endpoint — Request Body
{ "rejectReason": "Content needs more sources." }

API Reference — News (Author)

MethodEndpointDescription
GET/api/author/newsList the author's own articles with status filter
POST/api/author/newsCreate an article in draft or submit for review
PUT/api/author/news/[slug]Update own article (allowed in draft or rejected state)
DELETE/api/author/news/[slug]Delete own article

API Reference — Contact & Newsletter

MethodEndpointDescription
GET/api/admin/contactList all contact form submissions
PUT/api/admin/contact/[id]Toggle the replied status of a contact submission
GET/api/admin/newsletterList all newsletter subscribers

API Reference — Settings

MethodEndpointDescription
GET/api/admin/settings/generalGet general site settings
PUT/api/admin/settings/generalUpdate general settings (name, logo, social links, home view)
GET/api/admin/settings/cloudinaryGet Cloudinary configuration
PUT/api/admin/settings/cloudinaryUpdate Cloudinary credentials
GET/api/admin/settings/metadataGet SEO metadata settings
PUT/api/admin/settings/metadataUpdate SEO metadata (title, description, keywords, OG image)
GET/api/admin/settings/termsGet Terms & Privacy HTML content
PUT/api/admin/settings/termsUpdate Terms, Privacy Policy, and About Us content

API Reference — Dashboard

MethodEndpointDescription
GET/api/admin/dashboardReturns overview stats, chart data, and recent articles for the admin
GET/api/author/dashboardReturns the author's personal stats (article counts by status)

Data Models — User

FieldTypeDescription
nameStringDisplay name
emailString (unique)Login email address
passwordStringBcrypt-hashed password
roleEnumadmin, author, or user
imageStringProfile image URL (Cloudinary)
statusBooleanAccount active / inactive flag
softDeleteBooleanSoft-deletion flag (default: false)

Data Models — News

FieldTypeDescription
titleStringArticle headline
slugString (unique)URL-friendly identifier (auto-generated)
imageStringFeatured image URL (Cloudinary)
shortDescStringSummary / excerpt for listing pages
bodyStringFull HTML article content from SunEditor
readTimeNumberEstimated reading time in minutes
authorObjectId → UserReference to the article's author
categoryObjectId → CategoryPrimary category reference
subCategoryObjectId → CategorySubcategory reference
statusEnumdraft | review | published | rejected
rejectReasonStringRejection reason provided by admin
publishedAtDateTimestamp when article was published
viewCountNumberIncremented on each public view
breakingNewsBooleanShow in breaking news ticker
latestBooleanShow in latest news section
featuredBooleanShow in featured section
positionNumberManual sort order
softDeleteBooleanSoft-deletion flag

Data Models — Category

FieldTypeDescription
nameStringCategory display name
slugString (unique)URL slug
parentObjectId → Categorynull for top-level; parent ID for subcategories
statusBooleanActive / inactive
featuredBooleanShow in featured navigation
positionNumberManual sort order

Data Models — Settings

NamespaceKey Fields
generalcompanyName, phone, address, logo, favicon, social links, homeView (classic/modern)
cloudinarycloudName, apiKey, apiSecret, folder, secureUrlBase
metadatatitle, applicationName, description, keywords, openGraphImage
termsPolicyterms, policy, aboutUs (rich HTML content)

Data Models — Contact & Newsletter

ModelFieldTypeDescription
ContactnameStringSubmitter's name
emailStringSubmitter's email
messageStringMessage body
isRepliedBooleanReplied status flag
NewsletteremailString (unique)Subscriber email address

Configuration

Homepage Layout

Switch between Classic and Modern homepage layouts from Admin → Settings → General → Home View. The change takes effect immediately without a rebuild.

Cloudinary

Configure from Admin → Settings → Cloudinary. Required fields:

SEO & Metadata

Go to Admin → Settings → Metadata to set the page title template, default description, keywords, and Open Graph / Twitter Card image.

Legal Pages

The About Us, Privacy Policy, and Terms & Conditions page content is fully editable from Admin → Settings using the rich text editor. No code changes required.

Deployment

Vercel (Recommended)

  1. Push the project to a GitHub or GitLab repository.
  2. Import the repository at vercel.com.
  3. Add all environment variables in the Vercel project settings.
  4. Click Deploy — Vercel auto-detects Next.js and configures the build.

Self-Hosted (Node.js)

# Build the production bundle
npm run build

# Start the production server
npm run start

Docker

Create a Dockerfile based on the official Next.js Docker example and pass environment variables at runtime via --env-file .env.

Production Checklist

Support

If you have questions, issues, or feature requests, please open a support ticket through your purchase platform's messaging system.

When reporting a bug, please include:

Documentation last updated: April 2026