
A modern headless WordPress starter built with Next.js 16, React 19, and TypeScript.
# Clone the repositorygit clone https://github.com/9d8dev/next-wp.gitcd next-wp# Install dependenciespnpm install# Set up environment variablescp .env.example .env.local# Edit .env.local with your WordPress URL and credentials# Start development serverpnpm dev
Your site is now running at http://localhost:3000.
Create a .env.local file in the root directory:
WORDPRESS_URL="https://your-wordpress-site.com" # Full WordPress URLWORDPRESS_HOSTNAME="your-wordpress-site.com" # Domain for image optimizationWORDPRESS_WEBHOOK_SECRET="your-secret-key-here" # Secret for cache revalidation
next-wp/├── app/ # Next.js App Router│ ├── api/│ │ ├── og/ # OG image generation│ │ └── revalidate/ # Cache revalidation webhook│ ├── pages/[slug]/ # Dynamic WordPress pages│ ├── posts/│ │ ├── [slug]/ # Individual post pages│ │ ├── authors/ # Author archive│ │ ├── categories/ # Category archive│ │ └── tags/ # Tag archive│ ├── layout.tsx # Root layout│ ├── page.tsx # Homepage│ └── sitemap.ts # Dynamic sitemap├── components/│ ├── posts/ # Post-related components│ │ ├── post-card.tsx # Post card component│ │ ├── filter.tsx # Filter controls│ │ └── search-input.tsx # Search component│ ├── nav/ # Navigation components│ ├── theme/ # Theme toggle│ └── ui/ # shadcn/ui components├── lib/│ ├── wordpress.ts # WordPress API functions│ └── wordpress.d.ts # TypeScript definitions├── plugin/ # WordPress revalidation plugin├── menu.config.ts # Navigation configuration├── site.config.ts # Site metadata└── CLAUDE.md # AI assistant guidelines
Railway deploys the complete stack with one click: MySQL + WordPress + Next.js.
What's IncludedThe Railway template uses a custom WordPress Docker image (ghcr.io/9d8dev/next-wp-wordpress) with:
Deployment┌─────────┐ ┌───────────┐ ┌─────────┐│ MySQL │────▶│ WordPress │◀────│ Next.js ││ DB │ │ (CMS) │ │(Frontend)│└─────────┘ └───────────┘ └─────────┘
1. Complete WordPress Installation
https://wordpress-xxx.up.railway.app)2. Configure the Revalidation Plugin
The next-revalidate plugin is pre-installed and activated.
https://next-wp-xxx.up.railway.app)WORDPRESS_WEBHOOK_SECRET value3. Test the Setup
By default, the template deploys from the 9d8dev/next-wp repository. To customize:
Railway creates a copy of the repository in your GitHub. You can then:
WORDPRESS_URL - Your existing WordPress site URLWORDPRESS_HOSTNAME - WordPress domain (for images)WORDPRESS_WEBHOOK_SECRET - Generate a secure random string# Install dependenciespnpm install# Copy environment templatecp .env.example .env.local# Configure your WordPress connection in .env.local# Then start the dev serverpnpm dev
Required: Your WordPress site must have the REST API enabled (default since WP 4.7).
All WordPress interactions are centralized in lib/wordpress.ts:
getAllPosts(filters?) // Get all posts (max 100)getPostsPaginated(page, perPage, filters?) // Paginated postsgetPostBySlug(slug) // Single post by sluggetPostById(id) // Single post by ID
getAllCategories() // All categoriesgetCategoryBySlug(slug) // Category by sluggetAllTags() // All tagsgetTagBySlug(slug) // Tag by sluggetPostsByCategory(id) // Posts in categorygetPostsByTag(id) // Posts with tag
getAllAuthors() // All authorsgetAuthorBySlug(slug) // Author by sluggetPostsByAuthor(id) // Posts by authorgetAllPages() // All pagesgetPageBySlug(slug) // Page by slug
import { getPostsPaginated } from "@/lib/wordpress";const { data: posts, headers } = await getPostsPaginated(1, 9, {category: "news",search: "nextjs"});console.log(`Found ${headers.total} posts across ${headers.totalPages} pages`);
The starter uses Next.js cache tags for efficient revalidation:
WORDPRESS_WEBHOOK_SECRET valueWhen content changes in WordPress, only affected pages are revalidated.
Note: If using the Railway template, the plugin is pre-installed automatically.
Edit site.config.ts for site metadata:
export const siteConfig = {site_name: "Your Site",site_domain: "yourdomain.com",site_description: "Your site description"};
Edit menu.config.ts for navigation links:
export const mainMenu = [{ href: "/", label: "Home" },{ href: "/posts", label: "Blog" },// Add more links...];
This project uses shadcn/ui with Tailwind CSS. Customize colors in your CSS or update the shadcn theme.
your-site.com/wp-json/wp/v2/postsWORDPRESS_HOSTNAMEnext.config.ts has the correct remotePatternsWORDPRESS_WEBHOOK_SECRET matches in both WordPress and Next.js/api/revalidatepnpm dev # Start development serverpnpm build # Build for productionpnpm start # Start production serverpnpm lint # Run ESLint
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)MIT License - see LICENSE for details.
Built with Next.js, Tailwind CSS, shadcn/ui, and brijr/craft.
Created by Bridger Tower and Cameron Youngblood at 9d8.