Admin CMS

Last updated on 2026-03-22

The admin CMS provides a complete content management interface. All admin pages share a layout with AdminSidebar and AdminHeader. On mobile, the sidebar collapses into a Sheet overlay accessible via a hamburger menu.

Dashboard Overview

Route: /admin

The main dashboard displays:

  • Stats cards — Total Posts, Pageviews (with trend), Subscribers (with trend), Avg. Reading Time using the StatsCard component
  • Top Performing Posts — table showing post title, views, and reading completion percentage
  • Pending Comments — list of comments awaiting moderation with approve/reject actions
  • Recent Activity — timeline of recent events (posts published, comments received, subscribers joined) via ActivityTimeline
  • Quick actions — "New Post" button and "View Site" link in the header
import { StatsCard } from "@/components/admin/stats-card"
import { ActivityTimeline } from "@/components/admin/activity-timeline"
import { StatusBadge } from "@/components/admin/status-badge"

Dashboard Layout

┌──────────┬──────────┬──────────┬──────────┐
│  Total   │  Page-   │  Sub-    │  Avg.    │
│  Posts   │  views   │ scribers │  Read    │
├──────────┴──────────┼──────────┴──────────┤
│ Top Performing      │ Pending Comments    │
│ Posts (table)       │ (approve/reject)    │
├─────────────────────┴─────────────────────┤
│ Recent Activity (timeline)                │
└───────────────────────────────────────────┘

Posts List

Route: /admin/posts

Data table listing all posts with:

  • Status tabs — All, Published, Draft, Scheduled pill-style filter buttons
  • Search — text input to filter posts by title
  • Bulk actions — select multiple posts via checkboxes, then Publish or Delete
  • Table columns — checkbox, title (linked to edit page) with status badge, category, author (avatar + name), date (with tooltip for full date), views
  • Row actions — dropdown menu with Edit, Duplicate, and Delete options
  • Empty state — message with "New Post" CTA when no posts match filters
import { StatusBadge } from "@/components/admin/status-badge"

Post Editor (New)

Route: /admin/posts/new

Post creation editor with a split-pane layout:

  • Toolbar — back button, reading time badge, word count, Save Draft and Publish buttons with loading states
  • Main editor — distraction-free writing area with title input and content textarea
  • Settings sidebar (desktop only) — featured image upload zone, category select, tag toggles, excerpt textarea
  • SEO accordion — collapsible section with meta title (with character count), meta description (with character count), and slug input
  • Auto-slug — slug is auto-generated from the title
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"

Editor Layout

┌──────────────────────────────────────────────┐
│ ← Back   [Reading time] [Word count]  [Save] [Publish] │
├───────────────────────────────┬──────────────┤
│                               │ Featured     │
│ Post Title                    │ Image Upload │
│                               │              │
│ Post Content                  │ Category     │
│ (textarea)                    │ Tags         │
│                               │ Excerpt      │
│                               │ ▼ SEO        │
└───────────────────────────────┴──────────────┘

Edit Post

Route: /admin/posts/[id]/edit

Same editor layout as the new post page, pre-filled with existing post data from seed. Includes:

  • Status badge — shows current post status (Published, Draft, Scheduled)
  • Pre-filled fields — title, content, excerpt, category, tags, SEO settings
  • Save and Publish — buttons for saving changes or publishing updates

Media Library

Route: /admin/media

Image management with:

  • Upload zone — drag-and-drop area supporting PNG, JPG, GIF, and WebP up to 10MB
  • Search — filter media by filename or alt text
  • Image grid — responsive grid (2/3/4 columns) of image cards with hover scale effect, showing filename, dimensions, and file size
  • Detail Sheet — slide-out panel showing image preview, dimensions, file size, editable alt text, copyable URL, and delete button with confirmation dialog
  • Empty state — message when no media matches the search
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent } from "@/components/ui/alert-dialog"

Categories

Route: /admin/categories

Category management with:

  • Data table — columns for name, slug, description (truncated), and post count
  • Create dialog — name (with auto-slug generation), slug, and description fields
  • Edit button — per-row edit action
  • Delete confirmation — AlertDialog warning about uncategorized posts

Tags

Route: /admin/tags

Tag management with:

  • Data table — columns for checkbox, name, slug, and post count
  • Create dialog — name (with auto-slug generation) and slug fields
  • Merge tags — select 2+ tags and merge them into one (posts updated automatically)
  • Bulk delete — select multiple tags and delete them at once
  • Per-row delete — AlertDialog confirmation showing affected post count

Comments

Route: /admin/comments

Comment moderation with:

  • Status tabs — All, Pending, Approved, Spam with count badges
  • Comment cards — each showing author avatar, name, linked post title, relative timestamp, and comment content
  • Moderation actions — Approve (checkmark), Reject (X), Mark as Spam (flag) icon buttons with tooltips
  • Bulk actions — select multiple comments via checkboxes, then Approve All or Delete All
  • Empty state — contextual message based on active tab

Subscribers

Route: /admin/subscribers

Newsletter subscriber management:

  • Stats cards — Total Subscribers (with trend), Active count, Unsubscribed count
  • Search — filter subscribers by email
  • Data table — columns for email, subscribe date, source (organic/import/manual), and status badge (Active/Unsubscribed)
  • Add dialog — manually add a subscriber by email
  • CSV export — export subscriber list button
  • Empty state — message when no subscribers match search
import { StatsCard } from "@/components/admin/stats-card"

Settings

Route: /admin/settings

Site configuration organized into 4 tabs:

General Tab

  • Blog name and description fields
  • Logo upload zone
  • Favicon upload zone

SEO Tab

  • Meta title template (with %s placeholder)
  • Default meta description (with character count)
  • Default OG image upload (1200x630)
  • robots.txt toggle switch

Integrations Tab

  • Analytics — tracking ID input (e.g., G-XXXXXXXXXX)
  • Comments — provider select (Native, Disqus, Giscus)
  • Newsletter — provider select (Resend, ConvertKit, Mailchimp) with API key input

Advanced Tab

  • Code injection — custom head and body code textareas (monospace font)
  • Social links — GitHub, Twitter, LinkedIn, and RSS URL inputs

Each tab has its own "Save Changes" button with loading state.

Analytics

Route: /admin/analytics

Data visualization dashboard:

  • Stats cards — Total Pageviews, Unique Visitors, Avg. Session Duration, Bounce Rate (all with trend indicators)
  • Pageview chart — area/line chart showing views and unique visitors over time via PageviewChart
  • Traffic sources — pie chart breakdown via TrafficSourceChart
  • Post views — bar chart of top-performing posts via PostViewsChart
  • Reading completion — progress bars showing completion percentage per post
  • Subscriber growth — line chart showing total and new subscribers over time via SubscriberGrowthChart
import { StatsCard } from "@/components/admin/stats-card"
import {
  PageviewChart,
  TrafficSourceChart,
  SubscriberGrowthChart,
  PostViewsChart,
} from "@/components/admin/analytics-chart"

Analytics Layout

┌──────────┬──────────┬──────────┬──────────┐
│ Pageviews│ Visitors │ Avg.     │ Bounce   │
│          │          │ Session  │ Rate     │
├──────────┴──────────┼──────────┴──────────┤
│ Pageview Chart      │ Traffic Sources     │
│ (area/line)         │ (pie chart)         │
├─────────────────────┼─────────────────────┤
│ Post Views          │ Reading Completion  │
│ (bar chart)         │ (progress bars)     │
├─────────────────────┴─────────────────────┤
│ Subscriber Growth (line chart)            │
└───────────────────────────────────────────┘

Authors

Route: /admin/authors

Author team management:

  • Data table — columns for author (avatar + name), email, role badge, post count, and last active date
  • Invite dialog — email input and role select (Admin, Editor, Author) with "Send Invitation" button
  • Edit button — per-row edit action
  • Remove confirmation — AlertDialog warning that the author's posts will remain

Scheduled Posts

Route: /admin/scheduled

Upcoming post schedule:

  • Timeline cards — each showing post title (linked to editor), scheduled date and time, author avatar and name, category badge
  • Actions per post — Edit, Publish Now, and Cancel buttons
  • Empty state — message with "Create Post" CTA when no posts are scheduled

Mobile Responsiveness

The admin sidebar uses useIsMobile() to detect viewport width:

  • Desktop (768px+): Fixed sidebar with icon + label navigation
  • Mobile (<768px): Sidebar collapses, accessible via hamburger menu in AdminHeader as a Sheet overlay