npm package: @prismetic/next-preview-core
Description: Hybrid static/preview architecture for Next.js + Strapi projects
Author: Prismetic Group FZ LLC
Latest version: 1.0.16

# @prismetic/next-preview-core

Hybrid static/preview architecture for Next.js + Strapi projects.

Enables a production build that is a pure static export and a preview build hosted on S3 that fetches live Strapi content directly from the browser on page load — no Node.js server required.

## Installation

```bash
npm install @prismetic/next-preview-core
```

Also requires `@tanstack/react-query` as a peer dependency:

```bash
npm install @tanstack/react-query
```

## Exports

### `PreviewProviders`

Wrap your preview layout in this provider to enable React Query caching. Layout data (Navbar, Footer) fetched once will not refetch on page navigation.

```jsx
// src/app/[locale]/layout.jsx
import { PreviewProviders } from "@prismetic/next-preview-core";

const isPreview = process.env.NEXT_PUBLIC_APP_ENV === "preview";

return isPreview ? (
  <PreviewProviders refetchOnWindowFocus={true}>
    <YourPreviewLayoutFetcher locale={locale}>
      {children}
    </YourPreviewLayoutFetcher>
  </PreviewProviders>
) : (
  // ... static layout
);
```

### Best Practice: `refetchOnWindowFocus`
We highly recommend passing `refetchOnWindowFocus={true}` to `<PreviewProviders>`. 
* **Seamless Editing**: When a content editor updates data in Strapi and tabs back to the Preview website, the current page will automatically and silently refetch the freshest data.
* **Performance Optimized**: The provider intelligently uses `{ refetchType: 'active' }`. It will **only** refetch the page currently visible on the screen, completely ignoring any background cache queries (such as those generated by link-hover prefetching). This eliminates wasteful GraphQL requests.

### `withLivePreview(WrappedComponent, fetcherFn, cacheKeyGenerator)`

A Higher-Order Component that handles `useQuery`, loading/error states, and injects fetched data into your UI component.

| Argument | Type | Description |
|---|---|---|
| `WrappedComponent` | `React.Component` | Your pure UI component |
| `fetcherFn` | `async (props) => data` | Async function that fetches the data |
| `cacheKeyGenerator` | `(props) => string[]` | Returns the React Query cache key array |

```jsx
// src/components/preview/PreviewHome.jsx
"use client";

import { withLivePreview } from "@prismetic/next-preview-core";
import HomeUI from "@/app/[locale]/HomeUI";
import { fetchHomepageContent } from "@/api/queryModules";

export const PreviewHome = withLivePreview(
  HomeUI,
  ({ locale }) => fetchHomepageContent(locale),
  ({ locale }) => ["homepage", locale]
);
```

Then in your `page.jsx`:

```jsx
// src/app/[locale]/page.jsx
import { PreviewHome } from "@/components/preview/PreviewHome";

export default async function LocaleHomePage({ params }) {
  const { locale } = await params;
  const isPreview = process.env.NEXT_PUBLIC_APP_ENV === "preview";

  if (isPreview) return <PreviewHome locale={locale} />;

  // Production: fetch data server-side
  const data = await fetchHomepageContent(locale);
  return <HomeUI data={data} />;
}
```

## Deployment
```
npm login
npm run build
Commit the changes
npm version patch && npm publish --access public
```

## Build Commands

| Command | Output |
|---|---|
| `npm run build` | Production static export (data baked in at build time) |
| `npm run build:preview` | Preview static export (client-side fetch on page load) |

Add to your `package.json`:

```json
{
  "scripts": {
    "build": "next build",
    "build:preview": "NEXT_PUBLIC_APP_ENV=preview next build"
  }
}
```

## Local Development (npm link)

To test changes to this package in a project before publishing:

```bash
# 1. In this package directory
npm link

# 2. In your project directory
npm link @prismetic/next-preview-core
```

To unlink:
```bash
npm unlink @prismetic/next-preview-core
```