Skip to main content
Version: App Router (1.5+)

Introduction

HeadstartWP provides seamless data-fetching for Next.js App Router using modern async/await patterns. Unlike the Pages Router which uses React hooks, the App Router leverages Server Components for efficient server-side data fetching.

The data-fetching logic is powered by strategies and abstracts the data-fetching logic.

App Router Data Fetching

The @headstartwp/next/app package provides async functions specifically designed for Next.js App Router:

These functions:

  • Extract URL segments from route parameters
  • Handle WordPress pretty permalinks
  • Provide TypeScript support
  • Integrate with Next.js caching and revalidation

Basic Example

Here's how to fetch a page in an App Router Server Component:

app/about/page.tsx
import { queryPost } from '@headstartwp/next/app';
import { SafeHtml } from '@headstartwp/core/react';
import type { Metadata } from 'next';
import type { HeadstartWPRoute } from '@headstartwp/next/app';

async function query({ params }: HeadstartWPRoute) {
return queryPost({
routeParams: await params,
params: {
slug: 'about',
postType: 'page',
},
options: {
next: {
revalidate: 3600, // Revalidate every hour
},
},
});
}

export async function generateMetadata({ params }: HeadstartWPRoute): Promise<Metadata> {
const { seo } = await query({ params });
return seo.metadata;
}

export default async function AboutPage({ params }: HeadstartWPRoute) {
const { data, seo } = await query({ params });

return (
<main>
<h1>{data.post.title.rendered}</h1>
<SafeHtml html={data.post.content.rendered} />
</main>
);
}

Dynamic Routes

For dynamic routes like [...path], HeadstartWP automatically extracts URL segments:

app/[...path]/page.tsx
import { queryPost } from '@headstartwp/next/app';
import { SafeHtml } from '@headstartwp/core/react';
import type { HeadstartWPRoute } from '@headstartwp/next/app';

export default async function DynamicPage({ params }: HeadstartWPRoute) {
// URL segments are automatically parsed from params
const { data } = await queryPost({
routeParams: await params,
params: {
postType: ['post', 'page'],
},
});

return (
<article>
<h1>{data.post.title.rendered}</h1>
<SafeHtml html={data.post.content.rendered} />
</article>
);
}

Client Components

For Client Components that need reactive data or user interactions, you can still use the React hooks from @headstartwp/core/react:

Note: To use React hooks in App Router, you must wrap your root layout with the DataFetchingProvider from @headstartwp/core/react.

components/InteractivePost.tsx
'use client';

import { useFetchPost } from '@headstartwp/core/react';

export function InteractivePost({ slug }: { slug: string }) {
const { data, loading, error } = useFetchPost({
slug,
postType: 'post'
});

if (loading) return <div>Loading...</div>;
if (error) return <div>Error loading post</div>;

return (
<article>
<h1>{data.post.title.rendered}</h1>
{/* Interactive features here */}
</article>
);
}

What's Different from Pages Router?

Pages RouterApp Router
usePost() hookqueryPost() async function
Client-side rendering by defaultServer-side rendering by default
getStaticProps/getServerSidePropsDirect async/await in components
Manual ISR configurationBuilt-in revalidate options
useSWR for client-side cachingAutomatic request deduplication

The remaining sections in this documentation will focus on the App Router async functions. For React hooks usage in Client Components, refer to the React Hooks Docs.