Skip to main content

Theme Routing (Next.js App Router)

Official ReactPress themes use Next.js App Router (not Pages Router). Themes map CMS content via dynamic [slug] segments.

Official starter route table

PathFileContent type
/app/page.tsxHome / post list
/post/[slug]app/post/[slug]/page.tsxPost detail
/page/[slug]app/page/[slug]/page.tsxStatic page
/category/[slug]app/category/[slug]/page.tsxCategory archive
/tag/[slug]app/tag/[slug]/page.tsxTag archive
/searchapp/search/page.tsxSite search

Slugs come from aliases set in Admin for posts / pages; API returns the corresponding fields.

Post detail example

// app/post/[slug]/page.tsx
import { notFound } from 'next/navigation';
import { getArticleBySlug } from '@/lib/api';

export default async function PostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const article = await getArticleBySlug(slug);
if (!article) notFound();
return <ArticleLayout article={article} />;
}

SEO: generateMetadata

export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const article = await getArticleBySlug(slug);
if (!article) return {};
return {
title: article.metaTitle ?? article.title,
description: article.metaDescription ?? article.summary,
openGraph: {
title: article.metaTitle ?? article.title,
images: article.cover ? [{ url: article.cover }] : [],
},
};
}

Works with the SEO plugin and site settings.

Optional: catch-all routes

Multi-level paths such as knowledge bases can use [...segments]:

// app/knowledge/[...slug]/page.tsx
export default async function KnowledgePage({
params,
}: {
params: Promise<{ slug: string[] }>;
}) {
const { slug } = await params;
const path = slug.join('/');
// fetch by path…
}

Data fetching

Themes request API uniformly through Toolkit — never connect to the database directly. See Theme development.

Further reading