NB Frontend Architecture Details

News Portal is a comprehensive, bilingual (Bangla/English) news portal built with modern web technologies. It serves as both a public-facing news website and a full-featured admin dashboard for journalists, editors, and administrators to manage news content, videos, categories, and user roles.

GitHub: newsportal website

Type: Next.js 15 App Router application with TypeScript

License: ISC

🛠️ Tech Stack

LayerTechnology
FrameworkNext.js 15.x (App Router)
UI LibraryReact 19.x
LanguageTypeScript (strict mode)
StylingTailwind CSS v4.1 + Custom CSS
UI ComponentsRadix UI primitives + custom shadcn-style components
IconsLucide React
State ManagementReact hooks (useState, useEffect, useCallback, useRef)
Data FetchingAxios with interceptors
CarouselEmbla Carousel (React)
ChartsRecharts
NotificationsSonner (toast)
YouTube@next/third-parties

📁 Directory Structure

src/
├── app/ # Next.js App Router
│ ├── layout.tsx # Root layout (SEO, GA, schema.org)
│ ├── page.tsx # Home page (skeleton wrapper)
│ ├── (root)/ # Grouped routes (public site)
│ │ ├── layout.tsx # Public layout with HomeLayout
│ │ ├── page.tsx # HomePage component
│ │ ├── _components/ # Home page sections
│ │ │ ├── HomeLayout.tsx # Header+Footer wrapp
│ │ │ └── ...
│ │ ├── news/ # News routes
│ │ │ ├── page.tsx # Redirects to all-news
│ │ │ └── ...
│ │ ├── videos/ # Video listing
│ │ ├── about-us/, contact/, advertising/, etc.
│ │ └── sitemap.xml, rss.xml, robots.ts # SEO routes
│ └── admin/ # Admin panel routes
│ ├── login/page.tsx # Admin login
│ └── dashboard/
│ ├── layout.tsx # Dashboard sidebar wrapper
│ ├── page.tsx # Dashboard overview
│ ├── news/ # News management (super_admin)
│ ├── categories/ # Category management
│ ├── review-reports/ # Editor review queue
│ ├── my-reports/ # Reporter's own articles
│ ├── manage-editorial/ # User management (super_admin)
│ ├── bulletins/ # Breaking news bulletins
│ └── videos/ # Video management
├── components/ # Reusable components
│ ├── ui/ # Radix-based primitives
│ │ ├── button.tsx, badge.tsx, alert.tsx
│ │ ├── dialog.tsx, select.tsx, table.tsx
│ │ ├── carousel.tsx, .tsx, skeleton.tsx
│ │ └── navigation-menu.tsx, tooltip.tsx
│ ├── layouts/ # Layout components
│ │ ├── Header.tsx # Sticky header with nav
│ │ ├── Footer.tsx # Site footer
│ │ ├── TopNews.tsx # Breaking news ticker
│ │ └── BackToTopButton.tsx
│ ├── dashboard/ # Admin dashboard components
│ │ ├── DashboardSidebar.tsx # Role-based navigation
│ │ ├── DashboardPage.tsx # Stats overview
│ │ ├── NewsTable.tsx # CRUD table with modals
│ │ ├── CategoriesPage.tsx # Category management
│ │ └── Add/Edit news dialogues
│ └── pages/ # Full page components
│ ├── PublicNewsDetailsPage.tsx
│ ├── AllPublicVideosPage.tsx
│ ├── AllBangladeshNews.tsx
│ └── ...
│ ├── map/ # Election map
│ │ ├── BangladeshElectionMap.tsx (SVG interactive)
│ │ ├── MapDistrictLabels.tsx
│ │ └── ElectionResultsTable.tsx
│ ├── category_based_news/
│ │ └── SectionLayout.tsx # Reusable news section
│ ├── header/
│ │ └── BreakingNews.tsx # Scrolling ticker
│ ├── NewsCard.tsx, VideoCard.tsx, CategoryBadge.tsx
│ ├── ShareButton.tsx, ShareIcon.tsx
│ ├── InfiniteNewsArticleLoader.tsx # Infinite scroll
│ ├── RamadanSVG.tsx, ArchiveSVG.tsx, etc.
│ └── ...
├── lib/ # Utilities & API layer
│ ├── api.ts # Axios instance + all endpoints
│ ├── auth.ts # Auth helpers (localStorage+cookies)
│ ├── buildNewsLink.ts # SEO-friendly URL builder
│ ├── buildVideoLink.ts
│ ├── categoryPills.tsx # Homepage filter pills
│ ├── categoryPillsData.ts
│ ├── staticCategories.ts # Fallback nav categories
│ ├── youtubeUtils.ts # YouTube ID extraction
│ ├── formData.ts # Date formatting
│ ├── utils.ts # cn() utility
│ ├── manifestos.ts # Party manifestos data
│ ├── voterStats.ts # Election statistics
│ └── ...
├── types/ # TypeScript interfaces
│ ├── index.ts # Barrel export
│ ├── news.ts # NewsItem, NewsResponse
│ ├── videos.ts # Video interface
│ ├── category.ts # Category interface
│ ├── user.ts # UserData, UserRole
│ ├── ramadan.ts # RamadanData
│ ├── bulletin.ts # Bulletin types
│ ├── api.ts # API response types
│ ├── party.ts # Political party types
│ └── bangladesh-map.ts # Map data types
├── data/ # Static data files
│ ├── party_data.ts # Election party data
│ ├── map_path_data.ts # SVG map coordinates
│ ├── area_map_to_seat.ts # District mapping
│ ├── editorial_info.ts
│ ├── contact_info.ts
│ ├── bd_divisions.ts, bd_district.ts, bd_upazilas.ts
│ └── ...
├── hooks/ # Custom React hooks
│ ├── useCountdown.ts # Timer hook
│ └── use-mobile.ts # Mobile detection
├── middleware.ts # Next.js middleware (auth + redirects)
└── next.config.js # Next configuration
├── CSP headers (Google Analytics, Tag Manager)
├── Image remote patterns
├── Redirects (www to non-www)
└── Cache headers

🏗️ Architecture & Routing

App Router Structure

The application uses Next.js 15 App Router with route groups:

  1. /(root) → Public-facing website (grouped for layout isolation)
  2. /admin → Admin panel (protected by middleware)
  3. API routes/api/* (not shown in visible files; backend likely separate)

Route Pattern for News Articles

/news/[category]/[slug] → Dynamic article pages
├── Example: /news/category/slug
├── `buildNewsLink(id, title, category)` generates paths
└── Middleware redirects old `/news/id/title` → new format

Middleware Protection (middleware.ts)

  1. Role-based access control for admin routes
  2. News redirect: Old /news/123/title/news/category/title-123
  3. Protected routes: /admin/* requires token + role in cookies
  4. Role hierarchy:
  5. super_admin → full access
  6. editor → review-reports, my-reports, bulletins, videos
  7. reporter → my-reports only

Access Matrix:

RouteAllowed Roles
/admin/dashboard/manage-editorialsuper_admin
/admin/dashboard/newssuper_admin
/admin/dashboard/categoriessuper_admin
/admin/dashboard/review-reportssuper_admin, editor
/admin/dashboard/my-reportssuper_admin, editor, reporter
/admin/dashboard/bulletinssuper_admin, editor
/admin/dashboardall authenticated

🔐 Authentication & Authorization

Storage Strategy:

  1. localStorage → token, userData, role (client-side)
  2. Cookies → token, role (middleware SSR access)

Auth Flow (lib/auth.ts):

  1. Login → API returns { token, userData, role }
  2. setAuthData() stores in both localStorage and cookies
  3. Middleware reads cookies for route protection
  4. Role-based sidebar renders filtered navigation items
  5. Token automatically attached via Axios interceptor
  6. 401 responses trigger logout + redirect

📡 API Layer (lib/api.ts)

Axios instances:

  1. api (auth interceptors, no-cache headers) → authenticated requests
  2. cachedApi (no interceptors) → public static data

API Modules:

ModulePurposeAuth Required
authApi.login()Admin loginNo
newsApi.*CRUD, featured, popular, searchYes
reporterNewsApi.*Reporter-scoped newsYes (reporter+)
editorNewsApi.*Editor review/updateYes (editor+)
categoryApi.*Category CRUDYes (super_admin)
bulletinApi.*Breaking bulletinsYes (editor+)
videoApi.*Admin video CRUDYes
publicVideoApi.*Public video listingNo
userApi.*User CRUDYes (super_admin)
ramadanApi.*Prayer times, calendarNo
partyApi.*Election partiesNo
manifestoCommentApi.*Comments on manifestosNo
pollCommentApi.*Election poll commentsNo

News API Query Params (example):

/news/all-news?sortBy=createdAt&limit=4&search=something
&subCategory=mySubCat&category=myCat
&page=1&orderBy=asc

🎨 Components & Design System

Layout Components

ComponentRole
HomeLayoutWraps public pages: <Header /><main /><Footer /><TopNews /><BackToTopButton />
HeaderSticky: logo + search + date + nav bar + category pills + BreakingNews ticker
FooterSite links, contact, copyright
DashboardSidebarCollapsible sidebar with role-based menu + user info + logout

Header Component (components/layouts/Header.tsx)

Two-row design:

  1. Top bar: Logo (left), search (center), date/Live TV (right), mobile menu toggle
  2. Category pills row: Horizontal scroll pill navigation (categoryPills array) → filters content
  3. Main nav: Black background, 8 visible items max, "আরও" dropdown for overflow
  4. Breaking news ticker (BreakingNews.tsx) below nav
  5. Mobile: Hamburger menu → full-screen overlay with accordion subcategories

State Management:

  1. categoryLoading → fetches categories from API, falls back to staticCategories
  2. expandedCategory → mobile submenu state
  3. activePill → tracks current filter

UI Components (shadcn-style)

Radix UI primitives wrapped with Tailwind:

  1. Button, Badge, Alert, Input, Select, Dialog, Table, Carousel, Skeleton, Tooltip, NavigationMenu

🏠 Homepage Architecture (app/(root)/_components/HomePage.tsx)

Layout pattern:

<div className="max-w-7xl mx-auto bg-gray-50">
<div className="flex flex-col lg:flex-row gap-6 py-6">
{/* Left: News Grid (2/3 width) */}
<div className="flex-1 lg:w-2/3">
<FeaturedNewsSlider /> {/* Large hero + 6 thumbnails */}
<SectionLayout title="My title 1" category="My Category 1" columns={2} count={4} />
<SectionLayout title="My title 2" category="My Category 2" columns={4} count={8} />
{/* More sections... */}
</div>

{/* Right: Sidebar (1/3 width) */}
<div className="lg:w-1/3 flex flex-col">
<RamadanTimer2 />
<EidBanner />
<AdsForCall />
<NewsTitles />
<AdsSpace_300x250 />
<VideoNewsSection />
<AdsSpace_300x400 />
<PopularNews />
<AdsSpace_300x400 />
</div>
</div>

{/* Full-width bottom sections */}
<SectionLayout title="Title" category="Category" columns={5} count={10} />
{/* ... more categories ... */}
<AllNewsContentShort /> {/* Additional news grid */}
</div>

SectionLayout (components/category_based_news/SectionLayout.tsx)

Reusable component that:

  1. Fetches news by category/subCategory
  2. Renders grid of NewsCard components (3–5 columns responsive)
  3. Shows "Load More" button or infinite scroll (depending on config)
  4. Displays section title with category badge

📰 News Components

NewsCard (components/NewsCard.tsx)

Props: item: NewsItem, index: number

Features:

  1. Image (lazy-loaded, optimized with Next.js Image)
  2. Category + subcategory badges
  3. Title (line-clamp-2), description (line-clamp-3)
  4. Relative timestamp ("এইমাত্র", "X মিনিট আগে")
  5. Link: buildNewsLink(item.id, item.title, item.category)

PublicNewsDetailsPage (app/(root)/_components/pages/PublicNewsDetailsPage.tsx)

Full article view:

  1. Hero image + title + metadata (author, date, category)
  2. Article body (description)
  3. Social share buttons (Facebook, Twitter, WhatsApp, Copy Link)
  4. Related videos (3 from same category)
  5. Related news (4 from same category)
  6. Sticky sidebar? (depends on design)

InfiniteNewsArticleLoader (components/InfiniteNewsArticleLoader.tsx)

Infinite scroll implementation:

  1. Initial load: main article + 3 related articles
  2. Load more: fetches 2 articles at a time using rotating sort modes (views desc, createdAt desc, views asc, createdAt asc)
  3. Uses Intersection Observer on a trigger element at the bottom
  4. Prevents duplicates with loadedIdsRef Set
  5. Cycles through pages of each sort mode before exhausting all content

🗂️ Category System

Two-tier categories:

  1. Static categories (lib/staticCategories.ts) → Always displayed in nav (fallback)
  2. Dynamic categories (from API) → fetched on Header mount, merged with static

Category pills (below header):

  1. Defined in lib/categoryPillsData.ts + lib/categoryPills.tsx
  2. Special pills: latest, all-news, all-bangladesh, video, archive, book-fair, ramadan, election
  3. Active state highlighting
  4. Some pills have custom SVG icons (Ramadan, Book, Ballot, Map, Video)

Category filtering:

  1. Pills route to /?filter=pillId or direct /news/all-news?category=...
  2. Dropdown subcategories route to ?subCategory=X&category=Y

🗳️ Election Features

Bangladesh Election Map (components/map/BangladeshElectionMap.tsx)

Interactive SVG map of Bangladesh parliamentary constituencies:

  1. Zoom/Pan: Mouse wheel (desktop), pinch (mobile), double-tap reset
  2. Touch support: Drag when zoomed, gestures for mobile
  3. Color coding: Each constituency colored by winning party (from partyData)
  4. Tooltip: Shows constituency number, district name, winning party
  5. Responsive: Two-column layout on desktop (results table + map), stacked on mobile
  6. Data sources:
  7. data/map_path_data.ts → SVG path data for each area
  8. data/party_data.ts → party colors + winArea[] arrays
  9. data/area_map_to_seat.ts → area ID → district name mapping

Manifestos (app/(root)/manifesto/)

Data (lib/manifestos.ts):

  1. Party-wise manifestos (BNP, Jamaat, NCP, Islami Andolon)
  2. Each has partyId, flag/logo, name, englishName, slug, manifesto[] array

Pages:

  1. /manifesto → lists all parties with collapsible manifesto points
  2. /manifesto/[party] → individual party manifesto with comment section

Comment APIs: manifestoCommentApi → add/get comments per party (user-attributed)

🌙 Ramadan Timer (app/(root)/ramadan/)

RamadanTimer2 component (_components/RamadanTimer2.tsx):

  1. Swipeable card (prayer times ↔ iftar/sehri)
  2. Fetches data from ramadanApi.getTodayData()
  3. Displays 5 prayer times (Fajr, Dhuhr, Asr, Maghrib, Isha) with +2 min adjustment
  4. Shows Sehri (pre-dawn) and Iftar (sunset) times
  5. Auto-rotates every 10 seconds
  6. Manual swipe/drag interaction
  7. Bengali numerals

API (lib/api.tsramadanApi):

  1. getTodayData(city, country)
  2. getByDate(date, city, country)
  3. getMonthlyCalendar(year, month, city, country)
  4. getHijriCalendar(hijriYear, hijriMonth, city, country)
  5. getRamadanCalendar(hijriYear, city, country)

🎥 Videos System

Public video page: /videosAllPublicVideosPage

  1. Grid/List of videos (YouTube embeds or direct)
  2. VideoCard component with:
  3. YouTube thumbnail auto-generation (youtubeUtils.ts)
  4. Play button overlay
  5. Category badge
  6. Title + date
  7. publicVideoApi.getAll() + pagination/filtering

Admin video management:

  1. /admin/dashboard/videos → CRUD (super_admin, editor, reporter)
  2. videoApi for admin operations
  3. Validates YouTube URLs

🗃️ News Data Model (types/news.ts)

interface NewsItem {
id: number
title: string
description: string
category: string
subCategory: string | null
imageUrl: string
status: "draft" | "published" | "archived"
createdAt: string
updatedAt?: string
views: number
isBreakingNews?: number // 0/1 flag
isFeatured?: number // 0/1 flag
featurePriority?: number // For ordering featured
featureExpireAt?: string // Timestamp
location?: {
division: string
district: string
upazila: string
}
authorName?: string | null
authorId: number
author: User
tags?: string[]
keywords?: string[]
scheduledTime?: string | null // For scheduled publishing
}

🎛️ Admin Dashboard (app/admin/dashboard/)

DashboardSidebar (components/dashboard/DashboardSidebar.tsx)

Role-based navigation items:

  1. Dashboard (all)
  2. Manage Editorial (super_admin only)
  3. Bulletins (super_admin, editor)
  4. News (super_admin only)
  5. Categories (super_admin only)
  6. Review Reports (super_admin, editor)
  7. Videos (all)
  8. My Reports (super_admin, editor, reporter)

Each item shows icon + label, active state highlighting.

News Management (NewsTable.tsx)

Features:

  1. Table view with pagination (10 per page)
  2. Filters: category dropdown
  3. Columns: #, Image, Title, Category, Status, Breaking, Featured, Priority, Expire At, Author, Reporter, Created At, Actions
  4. Row expansion: Click to highlight
  5. Actions: Edit (dialog), Delete (confirm dialog)
  6. Breaking news toggle: Button toggles isBreakingNews
  7. Add News modal: Full form with image upload preview, tags/keywords (Enter to add), location selectors (division → district → upazila cascading), checkboxes for breaking/featured
  8. Edit News modal: Similar, only sends changed fields
  9. Image preview: FileReader base64 preview before upload
  10. Loading states: Skeleton rows
  11. Alerts: Success/error toasts (Sonner)

Form fields:

  1. Required: title, description, category, image
  2. Optional: authorName, subCategory, location, isBreakingNews, isFeatured, featurePriority, featureExpireAt, tags, keywords

🏢 Organization Schema (SEO)

Root layout (app/layout.tsx) embeds:

  1. Organization schema (Organization + WebSite)
  2. Google Analytics (lazy-loaded)
  3. Social meta (OpenGraph, Twitter)
  4. Preconnects to Google storage & GTM

🎯 Key Utilities

URL Builders

lib/buildNewsLink.ts:

buildNewsLink(id, title, category?)
// → /news/category/title-slug-id OR /news/title-slug-id

Slug: Bangla title → lowercase, spaces→dashes, remove special chars.

lib/buildVideoLink.ts:

buildVideoLink(videoId, title?)
// → /videos/[id]/[slug]

Date Formatting (lib/formData.ts)

formatDate() → "20 Mar 2026, 10:30 AM" (English)

Bangla number conversion used throughout Header and timers.

YouTube Utils (lib/youtubeUtils.ts)

  1. extractYouTubeInfo(url) → extracts video ID from various URL formats
  2. getYouTubeThumbnail(videoId) → returns img.youtube.com/vi/[id]/hqdefault.jpg

🗺️ Bangladesh Geographic Data (data/)

  1. bd_divisions.ts → Division names ( sylhet, dhaka, chittagong, etc.)
  2. bd_district.ts → Districts with division_id linkage
  3. bd_upazilas.ts → Upazilas linked to districts
  4. area_map_to_seat.ts → Map constituency IDs to human-readable names
  5. map_path_data.ts → SVG path/polygon definitions for each constituency

Used in:

  1. News filtering by location
  2. Election map rendering
  3. News creation forms (cascading selects)

📱 Responsive Design

  1. Mobile-first approach with Tailwind breakpoints (sm, md, lg, xl)
  2. Header:
  3. Desktop: Full nav + dropdowns
  4. Mobile: Hamburger → overlay with accordion submenus
  5. Election map:
  6. Touch gestures (pinch zoom, drag)
  7. Different zoom controls layout per breakpoint
  8. Tooltips positioned to avoid viewport edges
  9. News cards: 1 col mobile → 2 col md → 3-5 col lg depending on section
  10. Sidebar: Hidden on mobile, fixed left desktop (64w)

⚡ Performance Optimizations

  1. Image optimization:
  2. Next.js Image with loading="lazy" (except first/large hero with priority)
  3. quality={40} for thumbnails
  4. fill + object-cover for responsive containers
  5. Code splitting:
  6. Dynamic imports for heavy components (e.g., EidBanner conditionally loaded)
  7. Suspense boundaries on root page
  8. Caching:
  9. cachedApi for categories (no-auth, no-cache disabled)
  10. Static data in data/ files
  11. cache() wrapper for news details fetch
  12. Infinite scroll reduces initial bundle, loads on demand.
  13. Third-party scripts (GA, GTM) lazy-loaded with strategy="lazyOnload"

🔍 SEO & Metadata

Each route exports metadata (Next.js Metadata API):

  1. Dynamic title templates: %s | News title
  2. OpenGraph (images, title, description, locale bn_BD)
  3. Twitter cards (summary_large_image)
  4. Canonical URLs with alternates
  5. ** robots** (index/follow)
  6. Structured data (application/ld+json) for:
  7. Organization (with logo, social links)
  8. WebSite (SearchAction)
  9. NewsArticle (on article pages)

Sitemaps (dynamic):

  1. /sitemap.xml → routes
  2. /news-sitemap-1.xml → news URLs
  3. /video-sitemap.xml
  4. /category-pages-sitemap.xml
  5. /static-pages-sitemap.xml

RSS feed: /rss.xml route

🧪 Type Safety

  1. TypeScript strict mode (tsconfig.json)
  2. Comprehensive types in types/ directory
  3. API responses typed (though some any remain in legacy components)
  4. No @ts-ignore scattered (mostly clean)

🎯 Notable Features

  1. Breaking News Bulletins (BulletinTable) → Quick push to top of site
  2. Featured News RotationfeaturePriority, featureExpireAt for time-bound highlights
  3. News SchedulingscheduledTime for future publish
  4. Search → Global search bar → /news/all-news?search=query
  5. Social Sharing → Share buttons per article (Facebook, Twitter/X, WhatsApp, Copy)
  6. Infinite Scroll → article feed loads more indefinitely
  7. Election Map → Interactive SVG with zoom/pan/tooltip
  8. Ramadan Timer → Prayer/sehri/iftar times with swipe card
  9. Multi-language → Bangla numerals, Bangla date formatting, Bangla UI
  10. Commenting → on manifestos and polls (anonymous via hash or authenticated)

🚀 Getting Started

npm install # Install dependencies
npm run dev # Development at http://localhost:3000
npm run build # Production build
npm run start # Start production server
npm run lint # ESLint check

Environment variables:

  1. NEXT_PUBLIC_API_BASE_URL → Backend API endpoint
  2. NEXT_PUBLIC_BASE_URL → Site canonical URL

📊 Data Flow Summary

Client Request (e.g., /news/রাজনীতি/Title-123)
Middleware
├─ Redirect old-style news URLs
└─ Check /admin auth (cookies)
Next.js Route Handler (Server Component)
├─ Extract news ID from slug
├─ Fetch article details (cached)
├─ Generate metadata (SEO)
└─ Render page
Client Component (PublicNewsDetailsPage)
├─ Display article
├─ Fetch related videos + news (parallel)
└─ Render share buttons

🧩 Dependencies

Core: next, react, react-dom, typescript

Styling: tailwindcss, clsx, tailwind-merge, tailwindcss-animate, autoprefixer, postcss

UI: @radix-ui/*, lucide-react, sonner, class-variance-authority

Utilities: axios, embla-carousel-react, recharts

Third-party: @next/third-parties (for YouTube embeds, etc.)

🎓 Best Practices Observed

  1. App Router with Server/Client component separation
  2. TypeScript strict with proper typing
  3. Component composition (small reusable pieces)
  4. Error boundaries (Next.js error.tsx files present)
  5. Loading states (loading.tsx + skeleton components)
  6. SEO-friendly (metadata, sitemaps, RSS, structured data)
  7. Accessibility (ARIA labels, keyboard navigation in dropdowns)
  8. Responsive (mobile-first Tailwind)
  9. Performance (image optimization, lazy loading, caching)
  10. Security (CSP headers, XSS protection, no eval)

This codebase represents a production-grade news portal with a full editorial workflow (reporter → editor → publisher), role-based access control, rich media support, and Bangladesh-focused features (election mapping, Bangla numerals, Ramadan times).