### Usage Example: Fetching Posts with Filtering and Error Handling Source: https://github.com/9d8dev/next-wp/blob/main/README.md Demonstrates how to use the `getAllPosts` function to fetch posts with filtering options and how to handle potential `WordPressAPIError` exceptions. ```typescript try { // Fetch posts with filtering const posts = await getAllPosts({ author: "123", category: "news", tag: "featured", }); // Handle errors properly } catch (error) { if (error instanceof WordPressAPIError) { console.error(`API Error: ${error.message} (${error.status})`); } } ``` -------------------------------- ### Environment Variables Setup (.env.local) Source: https://github.com/9d8dev/next-wp/blob/main/README.md Sets up the necessary environment variables for connecting to a WordPress site. Requires WordPress URL, hostname for image rendering, and a secret key for secure revalidation. ```bash WORDPRESS_URL="https://wordpress.com" WORDPRESS_HOSTNAME="wordpress.com" WORDPRESS_WEBHOOK_SECRET="your-secret-key-here" ``` -------------------------------- ### Example Usage of Search Functionality Source: https://github.com/9d8dev/next-wp/blob/main/README.md Demonstrates how to utilize the search functionality within a Next.js page component. It shows fetching search parameters from the URL and conditionally calling `getAllPosts` with or without a search query. ```typescript // In your page component import { getAllPosts } from '@/lib/wordpress'; // Assuming searchParams is available in your page component context // For App Router, you might access it via props: // export default async function Page({ searchParams }: { searchParams: { search?: string } }) { const { search } = await searchParams; const posts = search ? await getAllPosts({ search }) : await getAllPosts(); // ... render posts ... ``` -------------------------------- ### Next.js Cache Management Example Source: https://github.com/9d8dev/next-wp/blob/main/README.md Illustrates how to configure cache tags and revalidation intervals for Next.js 15. This is crucial for efficient data fetching and automatic revalidation of cached content. ```typescript // Example cache configuration { next: { tags: ["wordpress", "posts", `post-${id}`], revalidate: 3600, } } ``` -------------------------------- ### Example Next.js Posts Page with Server-Side Pagination Source: https://github.com/9d8dev/next-wp/blob/main/README.md Illustrates a Next.js page component (`app/posts/page.tsx`) that fetches paginated posts using server-side rendering. It handles query parameters for pagination and filtering, displays post count, and includes a `PaginationComponent`. ```typescript export default async function PostsPage({ searchParams }) { const params = await searchParams; const page = params.page ? parseInt(params.page, 10) : 1; const postsPerPage = 9; // Efficient server-side pagination const { data: posts, headers } = await getPostsPaginated( page, postsPerPage, { author: params.author, category: params.category, tag: params.tag, search: params.search } ); const { total, totalPages } = headers; return (

{total} posts found

{posts.map(post => )} {totalPages > 1 && }
); } ``` -------------------------------- ### Next.js Cache Tagging for Revalidation Source: https://github.com/9d8dev/next-wp/blob/main/CLAUDE.md Example of how to use Next.js cache tags within data fetching functions for granular content revalidation. This ensures that specific pieces of content are updated efficiently after changes in the WordPress backend. ```typescript return await fetch(API_URL, { next: { tags: ['posts', `post-${slug}`] } }); ``` -------------------------------- ### Migrate to Server-Side Pagination from Client-Side Source: https://github.com/9d8dev/next-wp/blob/main/README.md Compares client-side pagination using `getAllPosts` with the more efficient server-side pagination achieved through `getPostsPaginated`. Demonstrates the shift in data fetching and metadata retrieval. ```typescript // Before: Client-side pagination const allPosts = await getAllPosts({ author, category }); const page = 1; const postsPerPage = 9; const paginatedPosts = allPosts.slice((page - 1) * postsPerPage, page * postsPerPage); const totalPages = Math.ceil(allPosts.length / postsPerPage); // After: Server-side pagination const { data: posts, headers } = await getPostsPaginated(page, postsPerPage, { author, category }); const { total, totalPages } = headers; ``` -------------------------------- ### Server-Side Pagination: Fetching Paginated Posts Source: https://github.com/9d8dev/next-wp/blob/main/README.md Shows how to use the `getPostsPaginated` function to fetch a specific page of posts with server-side pagination and filtering. It also demonstrates how to access pagination headers. ```typescript // Fetch page 2 with 10 posts per page const response = await getPostsPaginated(2, 10, { author: "123", category: "news", search: "nextjs" }); const { data: posts, headers } = response; const { total, totalPages } = headers; ``` -------------------------------- ### Next.js Build and Development Commands Source: https://github.com/9d8dev/next-wp/blob/main/CLAUDE.md Common npm scripts for managing the Next.js development server, production build, and code quality checks. ```bash npm run dev npm run build npm run start npm run lint ``` -------------------------------- ### Media API Source: https://github.com/9d8dev/next-wp/blob/main/README.md Functions for fetching media items, such as featured images. ```APIDOC ## GET /api/media/{id} ### Description Retrieves featured media (images) with size information. ### Method GET ### Endpoint /api/media/{id} ### Parameters #### Path Parameters - **id** (number) - Required - The ID of the media item to retrieve. ### Response #### Success Response (200) - **data** (Media) - The media object, including size details. ### Response Example ```json { "data": { "id": 1, "url": "http://example.com/wp-content/uploads/image.jpg", "sizes": { "thumbnail": {"url": "http://example.com/wp-content/uploads/image-150x150.jpg"}, "medium": {"url": "http://example.com/wp-content/uploads/image-300x200.jpg"} } } } ``` ``` -------------------------------- ### Tags API Source: https://github.com/9d8dev/next-wp/blob/main/README.md Functions for fetching tags from the WordPress API. ```APIDOC ## GET /api/tags ### Description Fetches all available tags. ### Method GET ### Endpoint /api/tags ### Response #### Success Response (200) - **data** (Array) - An array of tag objects. ### Response Example ```json { "data": [ { "id": 1, "name": "Featured", "slug": "featured" } ] } ``` ``` ```APIDOC ## GET /api/tags/{id} ### Description Retrieves a specific tag. ### Method GET ### Endpoint /api/tags/{id} ### Parameters #### Path Parameters - **id** (number) - Required - The ID of the tag to retrieve. ### Response #### Success Response (200) - **data** (Tag) - The tag object. ### Response Example ```json { "data": { "id": 1, "name": "Featured", "slug": "featured" } } ``` ``` ```APIDOC ## GET /api/tags/slug/{slug} ### Description Gets a tag by its slug. ### Method GET ### Endpoint /api/tags/slug/{slug} ### Parameters #### Path Parameters - **slug** (string) - Required - The slug of the tag to retrieve. ### Response #### Success Response (200) - **data** (Tag) - The tag object. ### Response Example ```json { "data": { "id": 1, "name": "Featured", "slug": "featured" } } ``` ``` ```APIDOC ## GET /api/posts/{postId}/tags ### Description Fetches all tags associated with a post. ### Method GET ### Endpoint /api/posts/{postId}/tags ### Parameters #### Path Parameters - **postId** (number) - Required - The ID of the post. ### Response #### Success Response (200) - **data** (Array) - An array of tag objects associated with the post. ### Response Example ```json { "data": [ { "id": 1, "name": "Featured", "slug": "featured" } ] } ``` ``` ```APIDOC ## GET /api/tags/{tagId}/posts ### Description Gets all posts with a specific tag. ### Method GET ### Endpoint /api/tags/{tagId}/posts ### Parameters #### Path Parameters - **tagId** (number) - Required - The ID of the tag. ### Response #### Success Response (200) - **data** (Array) - An array of post objects tagged with the specified tag. ### Response Example ```json { "data": [ { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } ] } ``` ``` -------------------------------- ### TypeScript MediaSize Interface Source: https://github.com/9d8dev/next-wp/blob/main/README.md Defines the `MediaSize` TypeScript interface, detailing properties of different image sizes available for WordPress media attachments, including file name, dimensions, MIME type, and source URL. ```typescript interface MediaSize { file: string; width: number; height: number; mime_type: string; source_url: string; } ``` -------------------------------- ### Pages API Source: https://github.com/9d8dev/next-wp/blob/main/README.md Functions for fetching WordPress pages. ```APIDOC ## GET /api/pages ### Description Retrieves all WordPress pages. ### Method GET ### Endpoint /api/pages ### Response #### Success Response (200) - **data** (Array) - An array of page objects. ### Response Example ```json { "data": [ { "id": 1, "title": "About Us", "slug": "about-us", "content": "

Information about us.

" } ] } ``` ``` ```APIDOC ## GET /api/pages/{id} ### Description Gets a specific page by ID. ### Method GET ### Endpoint /api/pages/{id} ### Parameters #### Path Parameters - **id** (number) - Required - The ID of the page to retrieve. ### Response #### Success Response (200) - **data** (Page) - The page object. ### Response Example ```json { "data": { "id": 1, "title": "About Us", "slug": "about-us", "content": "

Information about us.

" } } ``` ``` ```APIDOC ## GET /api/pages/slug/{slug} ### Description Fetches a page by its slug. ### Method GET ### Endpoint /api/pages/slug/{slug} ### Parameters #### Path Parameters - **slug** (string) - Required - The slug of the page to retrieve. ### Response #### Success Response (200) - **data** (Page) - The page object. ### Response Example ```json { "data": { "id": 1, "title": "About Us", "slug": "about-us", "content": "

Information about us.

" } } ``` ``` -------------------------------- ### Authors API Source: https://github.com/9d8dev/next-wp/blob/main/README.md Functions for fetching WordPress authors. ```APIDOC ## GET /api/authors ### Description Fetches all WordPress authors. ### Method GET ### Endpoint /api/authors ### Response #### Success Response (200) - **data** (Array) - An array of author objects. ### Response Example ```json { "data": [ { "id": 1, "name": "John Doe", "slug": "john-doe" } ] } ``` ``` ```APIDOC ## GET /api/authors/{id} ### Description Gets a specific author by ID. ### Method GET ### Endpoint /api/authors/{id} ### Parameters #### Path Parameters - **id** (number) - Required - The ID of the author to retrieve. ### Response #### Success Response (200) - **data** (Author) - The author object. ### Response Example ```json { "data": { "id": 1, "name": "John Doe", "slug": "john-doe" } } ``` ``` ```APIDOC ## GET /api/authors/slug/{slug} ### Description Retrieves an author by slug. ### Method GET ### Endpoint /api/authors/slug/{slug} ### Parameters #### Path Parameters - **slug** (string) - Required - The slug of the author to retrieve. ### Response #### Success Response (200) - **data** (Author) - The author object. ### Response Example ```json { "data": { "id": 1, "name": "John Doe", "slug": "john-doe" } } ``` ``` ```APIDOC ## GET /api/authors/{authorId}/posts ### Description Gets all posts by a specific author. ### Method GET ### Endpoint /api/authors/{authorId}/posts ### Parameters #### Path Parameters - **authorId** (number) - Required - The ID of the author. ### Response #### Success Response (200) - **data** (Array) - An array of post objects by the specified author. ### Response Example ```json { "data": [ { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } ] } ``` ``` -------------------------------- ### TypeScript WPEntity Interface Source: https://github.com/9d8dev/next-wp/blob/main/README.md Defines the core `WPEntity` TypeScript interface, which includes common properties for WordPress content entities like ID, dates, status, and link. This serves as a base for more specific content type definitions. ```typescript interface WPEntity { id: number; date: string; date_gmt: string; modified: string; modified_gmt: string; slug: string; status: "publish" | "future" | "draft" | "pending" | "private"; link: string; guid: { rendered: string; }; } ``` -------------------------------- ### Environment Variables Configuration Source: https://github.com/9d8dev/next-wp/blob/main/CLAUDE.md Lists essential environment variables required for the Next.js application to connect to and manage a WordPress backend. These variables are typically defined in a .env file. ```plaintext WORDPRESS_URL WORDPRESS_HOSTNAME WORDPRESS_WEBHOOK_SECRET ``` -------------------------------- ### Default Fetch Options for WordPress API Calls (TypeScript) Source: https://github.com/9d8dev/next-wp/blob/main/README.md Defines default fetch options for all WordPress API calls in a Next.js application. Configures caching with revalidation every hour and sets API request headers. ```typescript // Default fetch options for all WordPress API calls const defaultFetchOptions = { next: { tags: ["wordpress"], revalidate: 3600, // 1 hour cache }, headers: { Accept: "application/json", "Content-Type": "application/json", }, }; ``` -------------------------------- ### Posts API Source: https://github.com/9d8dev/next-wp/blob/main/README.md Functions for fetching posts from the WordPress API, including filtering and pagination. ```APIDOC ## GET /api/posts ### Description Fetches posts with optional filtering by author, tag, category, or search query. Uses cache tags for efficient revalidation. Limited to 100 posts for performance. ### Method GET ### Endpoint /api/posts ### Parameters #### Query Parameters - **author** (string) - Optional - Filter posts by author ID. - **tag** (string) - Optional - Filter posts by tag slug. - **category** (string) - Optional - Filter posts by category slug. - **search** (string) - Optional - Search query for posts. ### Response #### Success Response (200) - **data** (Array) - An array of post objects. ### Response Example ```json { "data": [ { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } ] } ``` ``` ```APIDOC ## GET /api/posts/paginated ### Description **Recommended** - Fetches posts with server-side pagination and filtering. Returns both data and pagination headers for efficient large-scale post handling. ### Method GET ### Endpoint /api/posts/paginated ### Parameters #### Query Parameters - **page** (number) - Optional - The page number to retrieve (defaults to 1). - **perPage** (number) - Optional - The number of posts per page (defaults to 10). - **author** (string) - Optional - Filter posts by author ID. - **tag** (string) - Optional - Filter posts by tag slug. - **category** (string) - Optional - Filter posts by category slug. - **search** (string) - Optional - Search query for posts. ### Response #### Success Response (200) - **data** (Array) - An array of post objects for the current page. - **headers** (object) - Pagination information. - **total** (number) - Total number of posts matching the query. - **totalPages** (number) - Total number of available pages. ### Response Example ```json { "data": [ { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } ], "headers": { "total": 100, "totalPages": 10 } } ``` ``` ```APIDOC ## GET /api/posts/{id} ### Description Retrieves a specific post by ID with proper error handling. ### Method GET ### Endpoint /api/posts/{id} ### Parameters #### Path Parameters - **id** (number) - Required - The ID of the post to retrieve. ### Response #### Success Response (200) - **data** (Post) - The post object. ### Response Example ```json { "data": { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } } ``` ``` ```APIDOC ## GET /api/posts/slug/{slug} ### Description Fetches a post using its URL-friendly slug. ### Method GET ### Endpoint /api/posts/slug/{slug} ### Parameters #### Path Parameters - **slug** (string) - Required - The slug of the post to retrieve. ### Response #### Success Response (200) - **data** (Post) - The post object. ### Response Example ```json { "data": { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } } ``` ``` -------------------------------- ### Categories API Source: https://github.com/9d8dev/next-wp/blob/main/README.md Functions for fetching categories from the WordPress API. ```APIDOC ## GET /api/categories ### Description Retrieves all categories with cache invalidation support. ### Method GET ### Endpoint /api/categories ### Response #### Success Response (200) - **data** (Array) - An array of category objects. ### Response Example ```json { "data": [ { "id": 1, "name": "News", "slug": "news" } ] } ``` ``` ```APIDOC ## GET /api/categories/{id} ### Description Gets a specific category by ID with error handling. ### Method GET ### Endpoint /api/categories/{id} ### Parameters #### Path Parameters - **id** (number) - Required - The ID of the category to retrieve. ### Response #### Success Response (200) - **data** (Category) - The category object. ### Response Example ```json { "data": { "id": 1, "name": "News", "slug": "news" } } ``` ``` ```APIDOC ## GET /api/categories/slug/{slug} ### Description Fetches a category by its slug. ### Method GET ### Endpoint /api/categories/slug/{slug} ### Parameters #### Path Parameters - **slug** (string) - Required - The slug of the category to retrieve. ### Response #### Success Response (200) - **data** (Category) - The category object. ### Response Example ```json { "data": { "id": 1, "name": "News", "slug": "news" } } ``` ``` ```APIDOC ## GET /api/categories/{categoryId}/posts ### Description Gets all posts in a category, using proper cache tags. ### Method GET ### Endpoint /api/categories/{categoryId}/posts ### Parameters #### Path Parameters - **categoryId** (number) - Required - The ID of the category. ### Response #### Success Response (200) - **data** (Array) - An array of post objects belonging to the category. ### Response Example ```json { "data": [ { "id": 1, "title": "First Post", "slug": "first-post", "content": "

This is the content of the first post.

" } ] } ``` ``` -------------------------------- ### Dynamic Cache Tags for Pagination Source: https://github.com/9d8dev/next-wp/blob/main/README.md Demonstrates generating dynamic cache tags for pagination in a Next.js application. This strategy ensures that only relevant pagination pages are revalidated when content changes, optimizing performance. ```typescript // Dynamic cache tags based on query parameters ["wordpress", "posts", "posts-page-1", "posts-category-123"] ``` -------------------------------- ### SearchInput Component for Real-time Search Source: https://github.com/9d8dev/next-wp/blob/main/README.md The SearchInput component provides real-time search functionality with 300ms debouncing. It integrates with Next.js App Router for URL-based state management and maintains existing filters during searches. The component supports server-side rendering for SEO and combines search with other filter parameters. ```typescript import { useRouter, useSearchParams } from "next/navigation"; import { useState, useEffect } from "react"; interface SearchInputProps { defaultValue?: string; } export const SearchInput = ({ defaultValue = "" }: SearchInputProps) => { const router = useRouter(); const searchParams = useSearchParams(); const [searchTerm, setSearchTerm] = useState(defaultValue); useEffect(() => { const handler = setTimeout(() => { const params = new URLSearchParams(searchParams); if (searchTerm) { params.set("search", searchTerm); } else { params.delete("search"); } router.push(`?${params.toString()}`); }, 300); return () => { clearTimeout(handler); }; }, [searchTerm, router, searchParams]); return ( setSearchTerm(e.target.value)} /> ); }; ``` -------------------------------- ### WordPress API Search Functions Source: https://github.com/9d8dev/next-wp/blob/main/README.md This section lists key functions available in `lib/wordpress.ts` for interacting with the WordPress API. These functions enable searching for posts with various filters (search, author, tag, category) and also searching for specific content types like categories, tags, and authors. ```typescript // Search posts with combined filters getAllPosts({ search?: string, author?: string, tag?: string, category?: string }); // Search specific content types searchCategories(query: string); searchTags(query: string); searchAuthors(query: string); ``` -------------------------------- ### TypeScript FilterBar Component Props Source: https://github.com/9d8dev/next-wp/blob/main/README.md Defines the TypeScript interface for the `FilterBarProps` component, specifying the expected types for author, tag, and category lists, as well as selected filter states and change handler functions. ```typescript interface FilterBarProps { authors: Author[]; tags: Tag[]; categories: Category[]; selectedAuthor?: Author["id"]; selectedTag?: Tag["id"]; selectedCategory?: Category["id"]; onAuthorChange?: (authorId: Author["id"] | undefined) => void; onTagChange?: (tagId: Tag["id"] | undefined) => void; onCategoryChange?: (categoryId: Category["id"] | undefined) => void; } ``` -------------------------------- ### Pagination Response Structure Source: https://github.com/9d8dev/next-wp/blob/main/README.md Defines the structure of the response object returned by `getPostsPaginated`. It includes the actual data (posts) and metadata like total posts and total pages. ```typescript interface WordPressResponse { data: T; // The actual posts array headers: { total: number; // Total number of posts matching the query totalPages: number; // Total number of pages }; } ``` -------------------------------- ### PostCard Component for Displaying WordPress Posts Source: https://github.com/9d8dev/next-wp/blob/main/README.md The PostCard component fetches and displays featured media, author, and category for a WordPress post. It formats the date and uses dangerouslySetInnerHTML for the title and excerpt to handle HTML content. The component is styled with CSS classes for a card-like appearance with hover effects. ```typescript import { Post } from "@/lib/wordpress"; import Link from "next/link"; interface PostCardProps { post: Post; } export const PostCard = ({ post }: PostCardProps) => { const formattedDate = new Date(post.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); return (
{post.title}

{post.categoryName}

{formattedDate}

); }; ``` -------------------------------- ### Generate Dynamic OG Image (API Route) Source: https://github.com/9d8dev/next-wp/blob/main/README.md This code snippet demonstrates how to generate Open Graph images dynamically for posts and pages. It's designed to be used in an API route, accepting title and description as query parameters. The output is an image suitable for social media sharing. ```typescript `/api/og?title=Your Title&description=Your Description` ``` -------------------------------- ### WordPress API Error Handling Source: https://github.com/9d8dev/next-wp/blob/main/CLAUDE.md Illustrates the use of a custom WordPressAPIError class for consistent error handling during interactions with the WordPress API. This approach centralizes error management and provides structured error information. ```typescript class WordPressAPIError extends Error { constructor(message: string, public status: number) { super(message); this.name = 'WordPressAPIError'; } } try { // ... API call } catch (error) { if (error instanceof WordPressAPIError) { console.error(`API Error ${error.status}: ${error.message}`); } else { console.error('An unexpected error occurred'); } } ``` -------------------------------- ### WordPress API Error Handling Source: https://github.com/9d8dev/next-wp/blob/main/README.md Defines a custom error class for consistent API error management. It extends the built-in Error class and includes additional properties for status code and the endpoint that caused the error. ```typescript class WordPressAPIError extends Error { constructor( message: string, public status: number, public endpoint: string, ) { super(message); this.name = "WordPressAPIError"; } } ``` -------------------------------- ### Manual Revalidation with Next.js Cache Tags Source: https://github.com/9d8dev/next-wp/blob/main/README.md This TypeScript code shows how to manually revalidate various types of cached content using Next.js's `revalidateTag` function. It covers global tags, content type tags, pagination-specific tags, and individual item tags for granular cache invalidation. ```typescript import { revalidateTag } from "next/cache"; // Revalidate all WordPress content revalidateTag("wordpress"); // Revalidate specific content types revalidateTag("posts"); revalidateTag("categories"); revalidateTag("tags"); revalidateTag("authors"); // Revalidate specific items revalidateTag("post-123"); revalidateTag("category-456"); // Revalidate pagination-specific content revalidateTag("posts-page-1"); revalidateTag("posts-category-123"); revalidateTag("posts-search"); ``` -------------------------------- ### FilterPosts Component for Filtering WordPress Posts Source: https://github.com/9d8dev/next-wp/blob/main/README.md The FilterPosts component allows users to filter WordPress posts by tags, categories, and authors. It uses Next.js's useRouter hook to manage URL parameters for selected filters. The component renders Select dropdowns for each filter type and provides a reset functionality. ```typescript import { useRouter } from "next/navigation"; import { Select } from "./select"; // Assuming a Select component exists interface FilterPostsProps { authors: { id: string; name: string }[]; tags: { id: string; name: string }[]; categories: { id: string; name: string }[]; selectedAuthor?: string; selectedTag?: string; selectedCategory?: string; } export const FilterPosts = ({ authors, tags, categories, selectedAuthor, selectedTag, selectedCategory }: FilterPostsProps) => { const router = useRouter(); const handleFilterChange = (filterType: string, value: string) => { const params = new URLSearchParams(window.location.search); if (value === "All") { params.delete(filterType); } else { params.set(filterType, value); } router.push(`?${params.toString()}`); }; const handleResetFilters = () => { router.push("/posts"); }; const authorOptions = [{ id: "All", name: "All Authors" }, ...authors]; const tagOptions = [{ id: "All", name: "All Tags" }, ...tags]; const categoryOptions = [{ id: "All", name: "All Categories" }, ...categories]; return (
handleFilterChange("tag", value)} />