---
title: "Your own collections"
description: "Live preview for collections you define."
requested_language: fr
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/fr/next/payload/frontend/live-preview/custom-collections
version: unreleased (main)
docs_index: https://docs.systhema.app/fr/next/llms.txt
---
> This page isn't translated yet. Showing English.


When you add your own collection on top of Systhema, you get the same live preview — server/client mode, the localhost cookie fix, the auth-gated `/sys/preview` route — without re-implementing any of it. Two pieces:

**1. Point the admin at the preview** with `systhemaPreviewAdmin` (replaces the hand-rolled `generatePreviewPath` pair):

```ts
import { systhemaPreviewAdmin } from '@systhemaui/payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  versions: { drafts: true },
  admin: {
    // `prefix` is where your route lives; the preview path becomes `${prefix}/${slug}`.
    ...systhemaPreviewAdmin({ collection: 'posts', prefix: '/blog' }),
  },
  fields: [/* slug, title, ... */],
}
```

**2. Wrap your render** in `<SysthemaLivePreview>` with a single `view` — one `'use client'` component that renders **both** the published page and the live overlay (server and client mode). This is the whole integration:

```tsx
// app/(site)/blog/[slug]/page.tsx — a Server Component
import { draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
import { getPayload } from 'payload'
import config from '@payload-config'
import { SysthemaLivePreview, getPreviewDepth } from '@systhemaui/payload/next'
import PostView from './PostView'

export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  const { isEnabled: draft } = await draftMode()
  const payload = await getPayload({ config })
  const { docs } = await payload.find({
    collection: 'posts',
    where: { slug: { equals: slug } },
    draft,
    depth: getPreviewDepth(), // one depth, shared with the live overlay
    limit: 1,
    overrideAccess: draft,
  })
  const post = docs[0]
  if (!post) notFound()

  return <SysthemaLivePreview collection="posts" initialData={post} view={PostView} />
}
```

`view` takes `{ data }` (the doc — live, unsaved form state while previewing) and must be a `'use client'` component, since its reference crosses the server→client boundary:

```tsx title="app/(site)/blog/[slug]/PostView.tsx"
'use client'
import type { Post } from '@/payload-types'

export default function PostView({ data }: { data: Post }) {
  return (
    <main>
      <h1>{data.title}</h1>
      {/* ... */}
    </main>
  )
}
```

> [!TIP]
> **Advanced — keep the published page server-only.** The single `view` is rendered on public pages too, so it ships in the client bundle. To keep the published render fully server-side, use the two-prop form instead: a server-rendered `children` (public + initial paint) plus a `'use client'` `clientView` overlay.
>
> ```tsx
> <SysthemaLivePreview collection="posts" initialData={post} clientView={PostViewClient}>
>   <PostView post={post} />
> </SysthemaLivePreview>
> ```

The wrapper reads `livePreview.mode` itself — flip the global setting once and every collection follows. Exports (all from `@systhemaui/payload/next` unless noted):

| Export                                                      | Purpose                                                                                   |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `SysthemaLivePreview`                                       | mode-aware wrapper; pass a single `view` (simple) or `children` + `clientView` (advanced) |
| `LivePreviewClientView<T>`                                  | type for your `'use client'` `view`/`clientView` renderer (`{ data, aux }`)               |
| `getPreviewDepth()`                                         | the live-preview depth; pass to your `payload.find({ depth })`                            |
| `useSysthemaLivePreview<T>`                                 | low-level client hook for custom layouts / multiple previewed regions                     |
| `LivePreviewListener`                                       | the bare server-mode listener, for fully hand-rolled routes                               |
| `systhemaPreviewAdmin({ collection, prefix?, slugField? })` | the `admin.livePreview` + `preview` block — from `@systhemaui/payload`                    |

> [!NOTE]
> Custom collections whose route isn't under a Systhema-default prefix must pass `prefix` so the preview URL matches your route. `slugField` defaults to `'slug'` — pass `'id'` for id-keyed collections.
