diff --git a/package.json b/package.json
index 0e0dd3bf..56dd2fdc 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
},
"dependencies": {
"@payloadcms/db-postgres": "3.76.1",
+ "@payloadcms/live-preview-react": "^3.76.1",
"@payloadcms/next": "3.76.1",
"@payloadcms/richtext-lexical": "3.76.1",
"@payloadcms/ui": "3.76.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6c5cd4e9..6e4115c4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,6 +11,9 @@ importers:
'@payloadcms/db-postgres':
specifier: 3.76.1
version: 3.76.1(payload@3.76.1(graphql@16.12.0)(typescript@5.7.3))
+ '@payloadcms/live-preview-react':
+ specifier: ^3.76.1
+ version: 3.76.1(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
'@payloadcms/next':
specifier: 3.76.1
version: 3.76.1(@types/react@19.2.9)(graphql@16.12.0)(monaco-editor@0.55.1)(next@15.4.11(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.77.4))(payload@3.76.1(graphql@16.12.0)(typescript@5.7.3))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.7.3)
@@ -1360,6 +1363,15 @@ packages:
graphql: ^16.8.1
payload: 3.76.1
+ '@payloadcms/live-preview-react@3.76.1':
+ resolution: {integrity: sha512-UwOAi2w2oYzPDncyANxgKkWiXq0KSFN5ajFzT/9IybSWJ1F9N1FIMphTeoEaT58GBHfX8vx/Mbqb8MSmVjh1mA==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.1 || ^19.1.2 || ^19.2.1
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.1 || ^19.1.2 || ^19.2.1
+
+ '@payloadcms/live-preview@3.76.1':
+ resolution: {integrity: sha512-wD9955QDBlXRONKGsNpeB0Y2FBikUjifnPk2ydrE3vFn4H5X4WLekOc1lVOQ8XhAxn7lj7w3kJaARgjU54uSKQ==}
+
'@payloadcms/next@3.76.1':
resolution: {integrity: sha512-0d5Irrhr632OToX8hKRqDBZJN/2w9xbJJXcZnGZ73YB67Srcb/UYcdNjItahmCbA9APKqlmK2zihgVoQ5NN2wA==}
engines: {node: ^18.20.2 || >=20.9.0}
@@ -5513,6 +5525,14 @@ snapshots:
transitivePeerDependencies:
- typescript
+ '@payloadcms/live-preview-react@3.76.1(react-dom@19.2.1(react@19.2.1))(react@19.2.1)':
+ dependencies:
+ '@payloadcms/live-preview': 3.76.1
+ react: 19.2.1
+ react-dom: 19.2.1(react@19.2.1)
+
+ '@payloadcms/live-preview@3.76.1': {}
+
'@payloadcms/next@3.76.1(@types/react@19.2.9)(graphql@16.12.0)(monaco-editor@0.55.1)(next@15.4.11(@babel/core@7.29.0)(@playwright/test@1.58.2)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.77.4))(payload@3.76.1(graphql@16.12.0)(typescript@5.7.3))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.7.3)':
dependencies:
'@dnd-kit/core': 6.3.1(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
diff --git a/src/app/(frontend)/layout.tsx b/src/app/(frontend)/layout.tsx
index 084d9d1f..5b0c4498 100644
--- a/src/app/(frontend)/layout.tsx
+++ b/src/app/(frontend)/layout.tsx
@@ -2,8 +2,10 @@ import { Footer } from '@/components/Footer'
import { Header } from '@/components/Header'
import React from 'react'
import './styles.css'
+import { RefreshRouteOnSave } from '@/utilities/RefreshRouteOnSave'
+import { Metadata } from 'next'
-export const metadata = {
+export const metadata: Metadata = {
description: 'Um template base usando Payload em uma aplicação Next.js.',
title: 'Template Base do Payload',
}
@@ -14,6 +16,7 @@ export default async function RootLayout(props: { children: React.ReactNode }) {
return (
+
{children}
diff --git a/src/globals/SiteSettings.ts b/src/globals/SiteSettings.ts
index bc982cee..9aed4daa 100644
--- a/src/globals/SiteSettings.ts
+++ b/src/globals/SiteSettings.ts
@@ -77,4 +77,13 @@ export const SiteSettings: GlobalConfig = {
hooks: {
afterChange: [revalidate],
},
+ versions: {
+ drafts: {
+ autosave: {
+ interval: 1000,
+ },
+ schedulePublish: true,
+ },
+ max: 10,
+ },
}
diff --git a/src/payload-types.ts b/src/payload-types.ts
index 40158787..78597776 100644
--- a/src/payload-types.ts
+++ b/src/payload-types.ts
@@ -70,6 +70,7 @@ export interface Config {
users: User;
media: Media;
'payload-kv': PayloadKv;
+ 'payload-jobs': PayloadJob;
'payload-locked-documents': PayloadLockedDocument;
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
@@ -79,6 +80,7 @@ export interface Config {
users: UsersSelect | UsersSelect;
media: MediaSelect | MediaSelect;
'payload-kv': PayloadKvSelect | PayloadKvSelect;
+ 'payload-jobs': PayloadJobsSelect | PayloadJobsSelect;
'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect;
'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect;
'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect;
@@ -96,7 +98,13 @@ export interface Config {
locale: null;
user: User;
jobs: {
- tasks: unknown;
+ tasks: {
+ schedulePublish: TaskSchedulePublish;
+ inline: {
+ input: unknown;
+ output: unknown;
+ };
+ };
workflows: unknown;
};
}
@@ -182,6 +190,98 @@ export interface PayloadKv {
| boolean
| null;
}
+/**
+ * This interface was referenced by `Config`'s JSON-Schema
+ * via the `definition` "payload-jobs".
+ */
+export interface PayloadJob {
+ id: number;
+ /**
+ * Input data provided to the job
+ */
+ input?:
+ | {
+ [k: string]: unknown;
+ }
+ | unknown[]
+ | string
+ | number
+ | boolean
+ | null;
+ taskStatus?:
+ | {
+ [k: string]: unknown;
+ }
+ | unknown[]
+ | string
+ | number
+ | boolean
+ | null;
+ completedAt?: string | null;
+ totalTried?: number | null;
+ /**
+ * If hasError is true this job will not be retried
+ */
+ hasError?: boolean | null;
+ /**
+ * If hasError is true, this is the error that caused it
+ */
+ error?:
+ | {
+ [k: string]: unknown;
+ }
+ | unknown[]
+ | string
+ | number
+ | boolean
+ | null;
+ /**
+ * Task execution log
+ */
+ log?:
+ | {
+ executedAt: string;
+ completedAt: string;
+ taskSlug: 'inline' | 'schedulePublish';
+ taskID: string;
+ input?:
+ | {
+ [k: string]: unknown;
+ }
+ | unknown[]
+ | string
+ | number
+ | boolean
+ | null;
+ output?:
+ | {
+ [k: string]: unknown;
+ }
+ | unknown[]
+ | string
+ | number
+ | boolean
+ | null;
+ state: 'failed' | 'succeeded';
+ error?:
+ | {
+ [k: string]: unknown;
+ }
+ | unknown[]
+ | string
+ | number
+ | boolean
+ | null;
+ id?: string | null;
+ }[]
+ | null;
+ taskSlug?: ('inline' | 'schedulePublish') | null;
+ queue?: string | null;
+ waitUntil?: string | null;
+ processing?: boolean | null;
+ updatedAt: string;
+ createdAt: string;
+}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents".
@@ -287,6 +387,37 @@ export interface PayloadKvSelect {
key?: T;
data?: T;
}
+/**
+ * This interface was referenced by `Config`'s JSON-Schema
+ * via the `definition` "payload-jobs_select".
+ */
+export interface PayloadJobsSelect {
+ input?: T;
+ taskStatus?: T;
+ completedAt?: T;
+ totalTried?: T;
+ hasError?: T;
+ error?: T;
+ log?:
+ | T
+ | {
+ executedAt?: T;
+ completedAt?: T;
+ taskSlug?: T;
+ taskID?: T;
+ input?: T;
+ output?: T;
+ state?: T;
+ error?: T;
+ id?: T;
+ };
+ taskSlug?: T;
+ queue?: T;
+ waitUntil?: T;
+ processing?: T;
+ updatedAt?: T;
+ createdAt?: T;
+}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents_select".
@@ -338,6 +469,7 @@ export interface SiteSetting {
id?: string | null;
}[]
| null;
+ _status?: ('draft' | 'published') | null;
updatedAt?: string | null;
createdAt?: string | null;
}
@@ -356,10 +488,24 @@ export interface SiteSettingsSelect {
enabled?: T;
id?: T;
};
+ _status?: T;
updatedAt?: T;
createdAt?: T;
globalType?: T;
}
+/**
+ * This interface was referenced by `Config`'s JSON-Schema
+ * via the `definition` "TaskSchedulePublish".
+ */
+export interface TaskSchedulePublish {
+ input: {
+ type?: ('publish' | 'unpublish') | null;
+ locale?: string | null;
+ global?: 'site-settings' | null;
+ user?: (number | null) | User;
+ };
+ output?: unknown;
+}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "auth".
diff --git a/src/payload.config.ts b/src/payload.config.ts
index 28eb83c9..ef50879a 100644
--- a/src/payload.config.ts
+++ b/src/payload.config.ts
@@ -19,6 +19,10 @@ export default buildConfig({
importMap: {
baseDir: path.resolve(dirname),
},
+ livePreview: {
+ url: 'http://localhost:3000',
+ globals: ['site-settings'],
+ },
},
collections: [Users, Media],
globals: [SiteSettings],
diff --git a/src/utilities/RefreshRouteOnSave.tsx b/src/utilities/RefreshRouteOnSave.tsx
new file mode 100644
index 00000000..88ced874
--- /dev/null
+++ b/src/utilities/RefreshRouteOnSave.tsx
@@ -0,0 +1,10 @@
+'use client'
+import { RefreshRouteOnSave as PayloadLivePreview } from '@payloadcms/live-preview-react'
+import { useRouter } from 'next/navigation.js'
+import React from 'react'
+
+export const RefreshRouteOnSave: React.FC = () => {
+ const router = useRouter()
+
+ return router.refresh()} serverURL="http://localhost:3000" />
+}