使用 Next.js 应用路由器和 React 服务器组件构建的无头 WordPress
A modern headless WordPress starter built with Next.js 16, React 19, and TypeScript. %2C%20the%20hostname%20for%20Image%20rendering%20in%20Next%20JS%20(ie.%20wp.example.com)%2C%20and%20a%20secret%20key%20for%20secure%20revalidation&project-name=next-wp&repository-name=next-wp&demo-title=Next%20JS%20and%20WordPress%20Starter&demo-url=https%3A%2F%2Fwp.9d8.dev)
Live Demo | Video Tutorial | Headless Theme (761)
Need a WooCommerce version? Try next-woo
# Clone the repository
git clone https://github.com/9d8dev/next-wp.git
cd next-wp
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env.local
# Edit .env.local with your WordPress URL and credentials
# Start development server
pnpm dev
Your site is now running at http://localhost:3000.
packageManager field — enable with corepack enable)Create a .env.local file in the root directory:
WORDPRESS_URL="https://your-wordpress-site.com" # Full WordPress URL
WORDPRESS_HOSTNAME="your-wordpress-site.com" # Domain for image optimization
WORDPRESS_WEBHOOK_SECRET="your-secret-key-here" # Secret for cache revalidation
…
Railway deploys the complete stack with one click: MySQL + WordPress + Next.js.
The Railway template uses a custom WordPress Docker image (ghcr.io/9d8dev/next-wp-wordpress) with:
┌─────────┐ ┌───────────┐ ┌─────────┐
│ 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 dependencies
pnpm install
# Copy environment template
cp .env.example .env.local
# Configure your WordPress connection in .env.local
# Then start the dev server
pnpm 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:
getRecentPosts(filters?) // Recent posts (max 100)
getPostsPaginated(page, perPage, filters?) // Paginated posts with headers
getPostBySlug(slug) // Single post by slug (with _embed)
getPostById(id) // Single post by ID
getAllPostSlugs() // All slugs (for static generation)
getAllPostsForSitemap() // All slugs + modified dates
getAllCategories() // All categories
getCategoryById(id) // Category by ID
getCategoryBySlug(slug) // Category by slug
getAllTags() // All tags
getTagById(id) // Tag by ID
getTagBySlug(slug) // Tag by slug
getPostsByCategory(id) // Posts in category
getPostsByTag(id) // Posts with tag
getTagsByPost(postId) // Tags on a post
getAllAuthors() // All authors
getAuthorById(id) // Author by ID
getAuthorBySlug(slug) // Author by slug
getPostsByAuthor(id) // Posts by author
getAllPages() // All pages
getPageById(id) // Page by ID
getPageBySlug(slug) // Page by slug
getPostsByCategoryPaginated(categoryId, page, perPage)
getPostsByTagPaginated(tagId, page, perPage)
getPostsByAuthorPaginated(authorId, page, perPage)
searchCategories(query) // Search categories
searchTags(query) // Search tags
searchAuthors(query) // Search authors
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 = {
home: "/",
blog: "/posts",
// Add more links...
};
export const contentMenu = {
categories: "/posts/categories",
tags: "/posts/tags",
authors: "/posts/authors",
};
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/revalidateThe project uses Vitest for unit testing.
pnpm test # Run all tests
pnpm test:watch # Run in watch mode
Tests cover the core modules:
| Module | What's tested |
|---|---|
lib/utils |
cn() class merging with Tailwind deduplication |
lib/metadata |
stripHtml, truncateHtml, OG/Twitter metadata generation |
lib/wordpress |
API fetch layer, pagination, error handling, graceful fallbacks |
api/revalidate |
Webhook secret validation, content type routing, cache revalidation |
pnpm dev # Start development server
pnpm build # Build for production
pnpm start # Start production server
pnpm lint # Run ESLint
pnpm test # Run tests
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.
暂无开放 Issues,或尚未同步最近议题。