A modern headless WordPress starter built with Next.js 16, React 19, and TypeScript.
# 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.
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
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.
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: - Clone the repo locally - Make customizations (styling, components, pages) - Push changes → Railway auto-deploys
For template creators, see RAILWAY-SETUP.md for detailed instructions on creating your own Railway template.
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:
getAllPosts(filters?) // Get all posts (max 100)
getPostsPaginated(page, perPage, filters?) // Paginated posts
getPostBySlug(slug) // Single post by slug
getPostById(id) // Single post by ID
getAllCategories() // All categories
getCategoryBySlug(slug) // Category by slug
getAllTags() // All tags
getTagBySlug(slug) // Tag by slug
getPostsByCategory(id) // Posts in category
getPostsByTag(id) // Posts with tag
getAllAuthors() // All authors
getAuthorBySlug(slug) // Author by slug
getPostsByAuthor(id) // Posts by author
getAllPages() // All pages
getPageBySlug(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 server
pnpm build # Build for production
pnpm start # Start production server
pnpm 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.
$ claude mcp add next-wp \
-- python -m otcore.mcp_server <graph>