Overview
Newspaper is a production-ready news publishing template that delivers a complete media platform in a single codebase. It includes:
- A responsive public news portal with Classic and Modern homepage layouts
- A full-featured Admin Dashboard for content, authors, and settings
- An Author Dashboard with review-gated content submission
- Secure REST API routes backed by JWT authentication
- SEO-ready metadata management and auto-generated sitemap
- Cloudinary integration for all media uploads
Print / PDF: A print-optimised version is available at
/documentation-pdf.html. Open it in your browser and use
File → Print → Save as PDF.
Features
Public Portal
- Two homepage layouts: Classic and Modern (switchable from admin settings)
- Dynamic category and subcategory pages with pagination
- News detail pages with read time and social sharing
- Breaking news, latest news, featured, and most-viewed sections
- Newsletter subscription and contact form
- SEO-optimised metadata, auto-generated sitemap, dark/light theme, fully responsive
Admin Dashboard
- Overview dashboard with charts and statistics
- News Management: Create, edit, publish, reject, sort, and soft-delete articles
- Category Management: Hierarchical categories with drag-to-reorder
- Author Management: Create and manage author accounts
- Contact Submissions, Newsletter Subscribers, and full Site Settings
Author Dashboard
- Personal stats and rich text article creation (SunEditor)
- Submit articles for admin review
- Track status: Draft → Under Review → Published / Rejected
Technical Highlights
- JWT + NextAuth v5 with role-based access control
- Soft-delete for news and users; multi-stage news workflow
- Zod validation on both frontend and backend
- TanStack React Table with filtering, sorting, and search
- Standardised API responses and centralised error handling
Requirements
| Dependency | Minimum Version |
|---|
| Node.js | 18.18 or later |
| npm | 9+ (or pnpm / yarn / bun) |
| MongoDB | 6+ (local or Atlas) |
| Cloudinary account | Free tier or higher |
Installation
1. Extract the Package
Unzip the downloaded archive and open the project folder in your terminal.
2. Install Dependencies
npm install
3. Configure Environment Variables
cp .env.example .env
Open .env and fill in each value. See Environment Variables for details.
4. Create the First Admin Account
Insert an admin user document directly into MongoDB. Set role to "admin" and use a bcrypt-hashed password.
5. Start the Development Server
npm run dev
| URL | Description |
|---|
http://localhost:3000 | Public news portal |
http://localhost:3000/admin/dashboard | Admin dashboard |
http://localhost:3000/author/dashboard | Author dashboard |
http://localhost:3000/login | Login page |
http://localhost:3000/documentation | In-app documentation |
Environment Variables
Create a .env file in the project root:
# ─── Database ───────────────────────────────────────────────────
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/<db>
# ─── Authentication ──────────────────────────────────────────────
# Generate: openssl rand -base64 32
NEXTAUTH_SECRET=your-secret-key-here
# ─── Internal API URL ────────────────────────────────────────────
NEXT_API_URL=http://localhost:3000
# ─── Cloudinary ──────────────────────────────────────────────────
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
Tip: Cloudinary credentials can be updated at any time from Admin → Settings → Cloudinary without redeploying.
Tech Stack
| Layer | Technology |
|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 4, shadcn/ui, Radix UI |
| Database | MongoDB with Mongoose 8 |
| Authentication | NextAuth v5 (JWT + Credentials) |
| Rich Text | SunEditor |
| Media | Cloudinary |
| Forms | React Hook Form + Zod |
| State | Zustand |
| Tables | TanStack React Table |
| Charts | Recharts |
| Drag & Drop | dnd-kit |
| Icons | Lucide React, Tabler Icons |
Project Structure
template-newspapper/
├── public/
│ ├── documentation.html # Standalone documentation
│ └── documentation-pdf.html # Print-optimised documentation
│
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/login/ # Login page
│ │ │
│ │ ├── (public)/ # Public-facing pages
│ │ │ ├── layout.tsx # Header + Footer wrapper
│ │ │ ├── page.tsx # Homepage
│ │ │ ├── [category]/ # Category listing
│ │ │ ├── news/[slug]/ # News detail
│ │ │ ├── about-us/
│ │ │ ├── contact-us/
│ │ │ ├── privacy-policy/
│ │ │ ├── terms-and-conditions/
│ │ │ └── site-map/
│ │ │
│ │ ├── (dashboard)/ # Protected dashboard
│ │ │ ├── layout.tsx # Sidebar shell
│ │ │ ├── admin/
│ │ │ │ ├── dashboard/
│ │ │ │ ├── news/
│ │ │ │ ├── categories/
│ │ │ │ ├── authors/
│ │ │ │ ├── contacts/
│ │ │ │ ├── newsletters/
│ │ │ │ └── settings/
│ │ │ └── author/
│ │ │ ├── dashboard/
│ │ │ └── news/
│ │ │
│ │ ├── documentation/ # /documentation route
│ │ │
│ │ └── api/
│ │ ├── auth/[...nextauth]/
│ │ ├── admin/
│ │ ├── author/
│ │ └── landing/
│ │
│ ├── components/
│ │ ├── ui/ # shadcn/ui primitives
│ │ ├── form/ # Form field components
│ │ ├── shared/ # Header, Footer, layout
│ │ ├── dashboard/ # Dashboard widgets
│ │ └── data-table/ # TanStack table components
│ │
│ ├── lib/
│ │ ├── async-handler.ts
│ │ ├── authenticate.ts
│ │ ├── fetcher.ts
│ │ ├── routes.ts
│ │ ├── utils.ts
│ │ └── validation-schema.ts
│ │
│ ├── model/
│ │ ├── User.ts / News.ts / Category.ts
│ │ └── Contact.ts / Newsletter.ts / Settings.ts
│ │
│ ├── services/
│ │ └── auth.ts / news.ts / categories.ts / ...
│ │
│ ├── config/
│ │ ├── database.ts
│ │ ├── cloudinary.ts
│ │ └── constant.ts
│ │
│ ├── hooks/
│ │ ├── use-user.ts
│ │ └── use-mobile.ts
│ │
│ └── store/
│ ├── user-store.ts
│ ├── breadcrumb-store.ts
│ ├── category-store.tsx
│ └── table-store.ts
│
├── .env / .env.example
├── next.config.ts
├── tailwind.config.ts
├── tsconfig.json
└── package.json
Roles & Permissions
| Role | Access |
|---|
| admin | Full access to admin dashboard, all content, settings, and user management |
| author | Access to author dashboard; can create, edit, and submit own articles only |
| user | Reserved 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.
Login Flow
- User submits email and password on
/login. - The credentials provider calls
/api/admin/auth/login or /api/author/auth/login. - Backend verifies the password with bcrypt and issues a signed JWT (30-day expiry).
- NextAuth stores the token in a secure, HTTP-only session cookie.
- API requests include the token as
Authorization: Bearer <token>. - The
authenticate() middleware verifies the token and attaches the user to context.
Key Files
| File | Purpose |
|---|
src/app/api/auth/[...nextauth]/auth.ts | NextAuth configuration |
src/lib/authenticate.ts | JWT verification for API routes |
src/lib/async-handler.ts | API route wrapper with role-checking |
src/hooks/use-user.ts | React hook to read current user |
API — Auth Endpoints
| Method | Route | Auth | Description |
|---|
| POST | /api/admin/auth/login | — | Admin login; returns JWT |
| POST | /api/author/auth/login | — | Author login; returns JWT |
| GET | /api/admin/auth/me | Admin | Get admin profile |
| PUT | /api/admin/auth/me | Admin | Update admin profile |
| PUT | /api/admin/auth/password | Admin | Change admin password |
| GET | /api/author/auth/me | Author | Get author profile |
| PUT | /api/author/auth/me | Author | Update author profile |
| PUT | /api/author/auth/password | Author | Change author password |
API — Category Endpoints
| Method | Route | Auth | Description |
|---|
| GET | /api/admin/category | Admin | List all categories |
| POST | /api/admin/category | Admin | Create a new category |
| GET | /api/admin/category/[slug] | Admin | Get category with subcategories |
| PUT | /api/admin/category/[slug] | Admin | Update category |
| DELETE | /api/admin/category/[slug] | Admin | Delete category |
| PUT | /api/admin/category/sort | Admin | Reorder categories |
API — Author Endpoints (Admin)
| Method | Route | Auth | Description |
|---|
| GET | /api/admin/author | Admin | List all authors |
| POST | /api/admin/author | Admin | Create a new author account |
| PUT | /api/admin/author/[id] | Admin | Update author details |
| DELETE | /api/admin/author/[id] | Admin | Delete an author |
API — News Endpoints (Admin)
| Method | Route | Auth | Description |
|---|
| GET | /api/admin/news | Admin | Paginated news list with filters |
| POST | /api/admin/news | Admin | Create and publish an article |
| GET | /api/admin/news/[slug] | Admin | Get single article |
| PUT | /api/admin/news/[slug] | Admin | Update article |
| DELETE | /api/admin/news/[slug] | Admin | Soft-delete article |
| PUT | /api/admin/news/sort | Admin | Reorder articles |
| PUT | /api/admin/news/reject/[slug] | Admin | Reject submitted article with reason |
API — News Endpoints (Author)
| Method | Route | Auth | Description |
|---|
| GET | /api/author/news | Author | List own articles |
| POST | /api/author/news | Author | Create article (draft or review) |
| PUT | /api/author/news/[slug] | Author | Update own article |
| DELETE | /api/author/news/[slug] | Author | Delete own article |
API — Settings Endpoints
| Method | Route | Auth | Description |
|---|
| GET | /api/admin/settings/general | Admin | Get general settings |
| PUT | /api/admin/settings/general | Admin | Update general settings |
| GET | /api/admin/settings/cloudinary | Admin | Get Cloudinary settings |
| PUT | /api/admin/settings/cloudinary | Admin | Update Cloudinary settings |
| GET | /api/admin/settings/metadata | Admin | Get SEO metadata |
| PUT | /api/admin/settings/metadata | Admin | Update SEO metadata |
| GET | /api/admin/settings/terms | Admin | Get Terms & Privacy content |
| PUT | /api/admin/settings/terms | Admin | Update Terms & Privacy content |
API — Dashboard Endpoints
| Method | Route | Auth | Description |
|---|
| GET | /api/admin/dashboard | Admin | Stats, charts, and recent news |
| GET | /api/author/dashboard | Author | Author's personal stats |
API — Public Endpoints
| Method | Route | Description |
|---|
| GET | /api/landing/news-category | Active categories for navigation |
| GET | /api/landing/news/[slug] | Public news article detail |
| GET | /api/landing/latest-news | Latest published articles |
| GET | /api/landing/breaking-news | Breaking news articles |
| GET | /api/landing/category-wise-news/[catId]/[subId] | Paginated news by category |
| GET | /api/landing/category-wise-news/[catId]/[subId]/featured | Featured news in category |
| GET | /api/landing/category-wise-news/[catId]/[subId]/most-viewed | Most-viewed news in category |
| POST | /api/landing/contact | Submit contact form |
| POST | /api/landing/newsletter | Subscribe to newsletter |
| GET | /api/landing/settings | Public site settings |
Data Model — User
| Field | Type | Description |
|---|
name | String | Display name |
email | String (unique) | Login email address |
password | String | Bcrypt-hashed password |
role | Enum | admin, author, or user |
image | String | Profile image URL (Cloudinary) |
status | Boolean | Active / inactive |
softDelete | Boolean | Soft-deletion flag |
Data Model — News
| Field | Type | Description |
|---|
title | String | Article headline |
slug | String (unique) | URL-friendly identifier |
image | String | Featured image URL |
shortDesc | String | Summary / excerpt |
body | String | Full HTML article content |
readTime | Number | Estimated minutes to read |
author | ObjectId → User | Author reference |
category | ObjectId → Category | Primary category |
subCategory | ObjectId → Category | Subcategory |
status | Enum | draft, review, published, rejected |
rejectReason | String | Rejection reason |
publishedAt | Date | Publication timestamp |
viewCount | Number | View counter |
breakingNews | Boolean | Breaking news ticker flag |
latest | Boolean | Latest news section flag |
featured | Boolean | Featured section flag |
position | Number | Manual sort order |
softDelete | Boolean | Soft-deletion flag |
Data Model — Category
| Field | Type | Description |
|---|
name | String | Category display name |
slug | String (unique) | URL slug |
parent | ObjectId → Category | null for top-level; parent ID for subcategories |
status | Boolean | Active / inactive |
featured | Boolean | Show in featured navigation |
position | Number | Sort order |
Data Model — Settings
| Namespace | Key Fields |
|---|
general | companyName, phone, address, logo, favicon, social links, homeView |
cloudinary | cloudName, apiKey, apiSecret, folder, secureUrlBase |
metadata | title, applicationName, description, keywords, openGraphImage |
termsPolicy | terms, policy, aboutUs (rich HTML) |
Configuration — Homepage Layout
Switch between Classic and Modern layouts from Admin → Settings → General → Home View. The change takes effect immediately without a rebuild.
Configuration — Cloudinary
Configure from Admin → Settings → Cloudinary. Required fields:
- Cloud Name — from your Cloudinary dashboard
- API Key — from your Cloudinary dashboard
- API Secret — from your Cloudinary dashboard
- Upload Folder — destination folder (e.g.
newspaper) - Secure URL Base — e.g.
https://res.cloudinary.com
Configuration — SEO & Metadata
Go to Admin → Settings → Metadata to set the page title template, default description, keywords, and Open Graph / Twitter Card image.
Configuration — Theme
Supports Light and Dark modes via next-themes. Users can toggle from the header. Default follows system preference.
Deployment
Vercel (Recommended)
- Push the project to a GitHub or GitLab repository.
- Import the repository in Vercel.
- Add all environment variables in the Vercel project settings.
- Deploy — Vercel auto-detects Next.js and configures the build.
Self-Hosted (Node.js)
npm run build
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
- Set a strong, unique
NEXTAUTH_SECRET - Use MongoDB Atlas with a dedicated user and IP allowlist
- Enable HTTPS (Vercel handles this automatically)
- Set
NEXT_API_URL to your production domain - Update Cloudinary credentials from Settings → Cloudinary after first login
- Change the default admin password immediately after first login
- Configure Open Graph image and site metadata in Settings → Metadata
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:
- Your Node.js version (
node -v) - The error message and stack trace
- Steps to reproduce the issue
Documentation last updated: April 2026