A modern, SEO-optimized blog platform built with Payload CMS, Next.js 15, and deployed on Cloudflare infrastructure.
β¨ Full-Featured Blog
- Rich text editing with Payload's Lexical editor
- Draft/publish workflow with scheduling
- Version history and autosave
- SEO optimization built-in
- Image management with Cloudflare R2
π¨ Modern UI
- Built with Next.js 15 and React 19
- Styled with Tailwind CSS and shadcn/ui
- Responsive design
- Dark mode support
π Role-Based Access Control
- Admin, Marketing, Product, and Viewer roles
- Granular permissions for content management
- Secure authentication
π Cloudflare-Native
- D1 SQLite database
- R2 object storage for media
- Workers for edge deployment
- Global CDN distribution
π Content Collections
- Posts: Blog posts with full SEO support
- Authors: Author profiles with social links
- Categories: Content organization
- Tags: Topic tagging system
- Media: Optimized image handling
- Content Guide: Complete guide for content creators
- Deployment Guide: Technical deployment instructions
- Migration Script: Import existing blog content
- Node.js 18.20.2+ or 20.9.0+
- pnpm 9+ or 10+
- Cloudflare account
git clone <your-repo-url>
cd payload-cms
pnpm installCreate a .env file:
PAYLOAD_SECRET=your-secret-key # Generate with: openssl rand -hex 32
NEXT_PUBLIC_SITE_URL=http://localhost:3000pnpm run generate:typespnpm run devVisit:
- Frontend: http://localhost:3000
- Blog: http://localhost:3000/blog
- Admin Panel: http://localhost:3000/admin
- Navigate to http://localhost:3000/admin
- Register with:
- Name
- Password
- Role: Admin
Full-featured blog posts with:
- Rich text content (Lexical editor)
- SEO metadata (title, description, OG image, canonical URL)
- Featured images
- Author attribution
- Category and tag organization
- Draft/publish workflow
- Publishing scheduler
- Reading time estimation
- Version history
Author profiles including:
- Name and bio
- Avatar image
- Role (Marketing, Product, Engineering, Leadership)
- Social links (Twitter, LinkedIn, GitHub)
Broad content organization:
- Name and slug
- Description
- Color coding for badges
Specific topic tagging:
- Name and slug
- Used for filtering and discovery
Image management with:
- Cloudflare R2 storage
- Alt text for accessibility
- Caption and credit fields
- Multiple size variants (thumbnail, card, featured)
payload-cms/
βββ src/
β βββ app/
β β βββ (frontend)/ # Public-facing pages
β β β βββ blog/ # Blog pages
β β β β βββ page.tsx # Blog listing
β β β β βββ [slug]/ # Individual posts
β β β β βββ category/ # Category pages
β β β β βββ tag/ # Tag pages
β β β βββ page.tsx # Homepage
β β βββ (payload)/ # Admin panel
β β β βββ admin/ # Payload admin UI
β β βββ globals.css # Global styles
β βββ collections/ # Payload collections
β β βββ Posts.ts
β β βββ Authors.ts
β β βββ Categories.ts
β β βββ Tags.ts
β β βββ Media.ts
β β βββ Users.ts
β βββ components/
β β βββ blog/ # Blog components
β β β βββ BlogCard.tsx
β β β βββ RichText.tsx
β β βββ ui/ # shadcn/ui components
β β βββ card.tsx
β β βββ badge.tsx
β βββ lib/
β β βββ utils.ts # Utility functions
β βββ payload.config.ts # Payload configuration
β βββ payload-types.ts # Generated types
βββ scripts/
β βββ migrate-blog-content.ts # Migration script
βββ CONTENT_GUIDE.md # Content creator guide
βββ DEPLOYMENT.md # Deployment guide
βββ README.md # This file
| Category | Technology |
|---|---|
| CMS | Payload CMS 3.63 |
| Framework | Next.js 15.4 |
| UI Library | React 19.1 |
| Styling | Tailwind CSS 4.1 |
| Components | shadcn/ui |
| Database | Cloudflare D1 (SQLite) |
| Storage | Cloudflare R2 |
| Deployment | Cloudflare Workers |
| Editor | Lexical (Payload) |
| Language | TypeScript 5.7 |
# Set environment
export CLOUDFLARE_ENV=production
# Deploy (migrations + app)
pnpm run deployFor detailed deployment instructions, see DEPLOYMENT.md.
To migrate existing blog content:
- Create
data/existing-blog-posts.jsonwith your content - Run the migration script:
pnpm tsx scripts/migrate-blog-content.tsSee scripts/migrate-blog-content.ts for format details.
pnpm run dev # Start development server
pnpm run build # Build for production
pnpm run deploy # Deploy to Cloudflare
pnpm run deploy:database # Deploy database migrations only
pnpm run deploy:app # Deploy application only
pnpm run preview # Preview production build locally
pnpm run generate:types # Generate TypeScript types
pnpm run lint # Run ESLint
pnpm run test # Run tests| Role | Posts | Authors | Categories | Tags | Delete |
|---|---|---|---|---|---|
| Admin | β Create, Edit | β Create, Edit | β Create, Edit | β Create, Edit | β All |
| Marketing | β Create, Edit | β Create, Edit | β Create, Edit | β Create, Edit | β None |
| Product | β Create, Edit | β Create, Edit | β Create, Edit | β Create, Edit | β None |
| Viewer | Read only | Read only | Read only | Read only | β None |
Public users can only read published posts.
- Meta Tags: Custom title and description
- Open Graph: Social media preview images
- Canonical URLs: Avoid duplicate content
- No-Index: Control search indexing
- Keywords: Target keyword tracking
- Structured Data: Ready for schema markup
- Sitemap: Auto-generated from posts
- Reading Time: Auto-calculated
GraphQL support is currently limited due to upstream issues in Workers. REST API is fully functional.
This template requires Paid Workers plan due to bundle size (3MB limit). We're actively working to reduce bundle size.
Image cropping and focal point features are disabled on Workers due to lack of sharp support. Images are stored as-is with size variants generated.
- Content Guide: See CONTENT_GUIDE.md
- Deployment Guide: See DEPLOYMENT.md
- Payload Docs: https://payloadcms.com/docs
- Cloudflare Docs: https://developers.cloudflare.com
- Discord: https://discord.com/invite/payload
- GitHub Discussions: https://github.com/payloadcms/payload/discussions
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
MIT
Built with β€οΈ by the Tenki team
For questions or support, contact your engineering team.