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
StatsCardcomponent - 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
%splaceholder) - 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
AdminHeaderas a Sheet overlay