A production-ready blog with secure admin dashboard, rich MDX content, and optimized performance. Built for personal blogs and technical writing.
- Framework: Next.js 16 (App Router) + React 19 + TypeScript
- Database: PostgreSQL (Prisma ORM)
- Authentication: NextAuth.js v4 (JWT sessions)
- Styling: Vanilla CSS + MDX (Markdown + JSX)
- π Secure Admin Dashboard - Middleware-protected routes with rate limiting
- π Rich Content - Write posts in MDX with syntax highlighting
- π¨ Light/Dark Theme - Automatic theme switching with CSS variables
- β‘ Fast Performance - ISR caching + static generation (50-200ms response)
- π± Mobile-First Design - Responsive hamburger menu navigation, smooth animations
- π‘οΈ Enterprise Security - HSTS, XSS protection, secure sessions
- βΏ Accessibility - WCAG compliant with ARIA labels, skip links, and semantic HTML
- π SEO Optimized - Dynamic metadata, Open Graph, Twitter Cards, JSON-LD structured data
- βΎοΈ Infinite Scroll - Optional infinite scroll on archive page with loading states
- π― Code Quality - ESLint + Prettier configured for consistent code style
-
Clone the repository
git clone https://github.com/AparAgarwal/blog-website.git cd blog-website -
Install dependencies
npm install # or yarn install -
Environment Configuration Create a
.envfile in the root directory:# Get this from Neon dashboard (https://neon.tech) DATABASE_URL="postgresql://user:pass@host/db?sslmode=require" # Generate with: openssl rand -base64 32 NEXTAUTH_SECRET="your-secure-random-secret-key" # For local development NEXTAUTH_URL="http://localhost:3000"
-
Database Setup Initialize the database and generate the Prisma Client:
# Generate Prisma Client npx prisma generate # Push schema to database npx prisma db push # Seed the database with admin user npx prisma db seed
Note: The seed creates an admin user. Check the console output for credentials.
-
Run Development Server
npm run dev
Access the app at
http://localhost:3000.
npm run dev- Start development servernpm run build- Build production bundlenpm run start- Start production server
npm run lint- Run ESLint checksnpm run lint:fix- Auto-fix ESLint issuesnpm run format- Format code with Prettiernpm run format:check- Check code formatting
npx prisma generate- Generate Prisma Clientnpx prisma db push- Push schema to databasenpx prisma db seed- Seed database with initial datanpx prisma studio- Open Prisma Studio (database GUI)npx tsx scripts/backup-db.ts- Backup posts to JSON filenpx tsx scripts/restore-db.ts- Restore posts from JSON backup
βββ prisma/
β βββ schema.prisma # Database schema (Post, Admin, RateLimit models)
β βββ seed.ts # Database seeding script
β βββ migrations/ # Database migrations (if using migrate)
βββ src/
β βββ app/ # Next.js App Router
β β βββ admin/ # Admin dashboard routes (Protected)
β β βββ api/ # API Routes (Auth, etc.)
β β βββ posts/ # Public post views ([slug]) with dynamic metadata
β β βββ archive/ # Archive page with infinite scroll
β β βββ layout.tsx # Root layout with metadata and font configuration
β β βββ layout-client.tsx # Client-side layout with navigation
β βββ lib/
β β βββ db.ts # Global PrismaClient instance
β β βββ rate-limit.ts # Rate limiting utility
β βββ components/ # Reusable UI components
β β βββ PostList.tsx # Post list with optional infinite scroll
β β βββ PostForm.tsx # Post creation/editing form
β β βββ ThemeToggle.tsx # Dark/light theme switcher
β β βββ Spinner.tsx # Loading spinner component
β β βββ HeroSection.tsx # Homepage hero section
β β βββ CodeBlock.tsx # Syntax-highlighted code blocks
β β βββ ... # Other components
β βββ middleware.ts # Authentication protection rules
β βββ types/ # TypeScript type definitions
βββ scripts/
β βββ backup-db.ts # Database backup script
β βββ restore-db.ts # Database restore script
βββ public/ # Static assets
βββ .prettierrc # Prettier configuration
βββ eslint.config.mjs # ESLint configuration (flat config)
βββ next.config.ts # Next.js configuration
Posts are stored in PostgreSQL and rendered with MDX for safe, rich content. Create, edit, and publish posts through the admin dashboard at /admin.
The project includes built-in scripts for backing up and restoring your blog data:
Create a JSON backup of all posts to preserve your content:
npx tsx scripts/backup-db.tsThis will:
- Export all posts to
prisma/seed-data.json - Preserve post relationships (linked posts)
- Output backup statistics (number of posts backed up)
When to use:
- Before major database migrations
- Before deploying significant changes
- As part of regular backup strategy
- Before testing destructive operations
Restore posts from your backup file:
npx tsx scripts/restore-db.tsThis will:
- Clear all existing posts from the database
- Import posts from
prisma/seed-data.json - Restore post relationships and linked posts
- Display restore progress and statistics
Use cases:
- Recovering from accidental data deletion
- Migrating between databases
- Restoring to a previous state
- Setting up a development environment with production data
Enterprise-grade security:
- Middleware Protection - All admin routes protected at HTTP level
- Rate Limiting - Exponential backoff after 5 failed login attempts
- Strong Passwords - Minimum 12 characters required
- Secure Sessions - JWT with 30-day expiration, HttpOnly cookies
- Security Headers - HSTS, X-Frame-Options, CSP, and more
WCAG Accessibility:
- Semantic HTML - Proper heading hierarchy, article tags, navigation landmarks
- ARIA Labels - Comprehensive labeling for screen readers
- Skip Links - Jump to main content functionality
- Keyboard Navigation - Full keyboard accessibility for mobile menu
- Screen Reader Support - Proper roles and live regions for dynamic content
Admin features: Dashboard (/admin), Password change (/admin/settings), Explicit logout.
Deploy to Vercel + Neon PostgreSQL (both 100% free, no credit card):
- Create Database - Sign up at neon.tech, create project, copy connection string
- Push to GitHub - Commit your code to a GitHub repository
- Deploy to Vercel - Import repo at vercel.com, set environment variables
- Configure Domain - (Optional) Add custom domain in Vercel settings
π Full guide with troubleshooting: DEPLOYMENT.md
- DEPLOYMENT.md - Complete deployment guide with custom domain setup
- package.json - All dependencies and scripts
- Mobile-first hamburger menu with smooth animations
- Body scroll lock when menu is open
- Click-outside-to-close functionality
- Accessible with ARIA attributes
- Dynamic Open Graph and Twitter Card metadata for all pages
- JSON-LD structured data for blog posts
- Canonical URLs and proper meta descriptions
- Sitemap-ready structure
- Intersection Observer API for scroll animations
- Optional infinite scroll with loading states
- Image optimization with Next.js Image component
- Font preloading and display swap
- TypeScript strict mode enabled
- ESLint with flat config format
- Prettier for consistent formatting
- Comprehensive error handling
Contributions welcome! Feel free to open issues or submit pull requests.
MIT License - See LICENSE for details.
Built with β€οΈ using Next.js 16, Prisma, and PostgreSQL