npm package: @orion-studios/payload-nextjs-utils
Description: Next.js integration utilities for Payload CMS
Author: Orion Studios
Latest version: 0.1.1

# @orion-studios/payload-nextjs-utils

Next.js integration utilities for Payload CMS - page queries, site globals, media resolution, and Payload client management.

## Installation

```bash
npm install @orion-studios/payload-nextjs-utils
```

## Features

- **Payload Client Singleton**: Factory for creating cached Payload client
- **Page Queries**: Fetch pages by URL segments with Next.js caching
- **Site Globals**: Cached queries for header, footer, and site settings
- **Media Resolution**: Convert Payload media references to URLs
- **TypeScript Support**: Full type definitions
- **Next.js Integration**: Works with App Router and Pages Router

## Usage

### Setup: Create Payload Client

```typescript
// src/lib/payload.ts
import config from '@/payload.config'
import { createPayloadClient } from '@orion-studios/payload-nextjs-utils'

export const getPayloadClient = createPayloadClient(config)
```

### Page Queries

```typescript
// src/lib/pages.ts
import { getPayloadClient } from './payload'
import { createPageQueries } from '@orion-studios/payload-nextjs-utils'

export const { getPageBySegments, listPublishedPagePaths, pathToSegments } =
  createPageQueries(getPayloadClient)
```

```typescript
// src/app/[[...slug]]/page.tsx
import { getPageBySegments, listPublishedPagePaths } from '@/lib/pages'

export async function generateStaticParams() {
  const paths = await listPublishedPagePaths()
  return paths.map((path) => ({
    slug: path.split('/').filter(Boolean),
  }))
}

export default async function Page({
  params,
}: {
  params: Promise<{ slug?: string[] }>
}) {
  const { slug } = await params
  const page = await getPageBySegments(slug)

  if (!page) {
    notFound()
  }

  return (
    <div>
      <h1>{page.title}</h1>
      {/* Render page.layout blocks */}
    </div>
  )
}
```

### Site Globals

```typescript
// src/lib/site.ts
import { getPayloadClient } from './payload'
import { createSiteQueries } from '@orion-studios/payload-nextjs-utils'

export const { getSiteSettings, getHeader, getFooter } =
  createSiteQueries(getPayloadClient)
```

```typescript
// src/app/layout.tsx
import { getHeader, getFooter } from '@/lib/site'

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const header = await getHeader()
  const footer = await getFooter()

  return (
    <html>
      <body>
        <Header navItems={header.navItems} />
        {children}
        <Footer {...footer} />
      </body>
    </html>
  )
}
```

### Media Resolution

```typescript
import { resolveMedia } from '@orion-studios/payload-nextjs-utils'

// In your component
const media = resolveMedia(block.image)

if (media) {
  return <img src={media.url} alt={media.alt} />
}
```

## API Reference

### `createPayloadClient(config)`

Creates a Payload client singleton factory.

**Parameters:**
- `config`: Your Payload config (from `payload.config.ts`)

**Returns:** Function that returns cached Payload client

### `createPageQueries(getPayloadClient, contentTag?)`

Creates page query utilities.

**Returns:**
- `getPageBySegments(segments?, draft?)`: Fetch page by URL segments
- `listPublishedPagePaths()`: List all published page paths
- `pathToSegments(path)`: Convert path string to segments array

### `createSiteQueries(getPayloadClient, contentTag?)`

Creates site globals query utilities.

**Returns:**
- `getSiteSettings(draft?)`: Fetch site settings global
- `getHeader(draft?)`: Fetch header global
- `getFooter(draft?)`: Fetch footer global

### `resolveMedia(media)`

Converts Payload media reference to usable URL object.

**Parameters:**
- `media`: Media ID, object, or null

**Returns:** `{ url: string, alt: string } | null`

## Caching

All queries automatically use Next.js `unstable_cache` with the tag `website-content` (customizable via `contentTag` parameter). This enables:

- **Automatic Revalidation**: Cache is invalidated when content changes
- **Optimal Performance**: Cached queries are nearly instant
- **ISR Support**: Works with Incremental Static Regeneration

```typescript
// To revalidate cache
revalidateTag('website-content')
```

## Requirements

- Payload CMS 3.x
- Next.js 14+ or 15+

## License

MIT © Orion Studios