chore(templates): clean up templates dependencies (#7139)
- use react 19 types - no need for dotenv - next has their own dotenv file loader - disable deprecation warnings by default (newer node version spam you with it) - disable turbo by default as hmr is broken and we cannot test against it yet - remove ts-node mention in tsconfig as it's not used anymore - remove unused packages - [fix: potential seed issues due to parallel payload operations being on the same transaction](f899f6a408) andb3b565dd75@DanRibbens can you sense-check this? I do remember that anything running in parallel should never be on the same transaction --------- Co-authored-by: Paul Popus <paul@nouance.io>
This commit is contained in:
@@ -22,8 +22,8 @@
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-canary.53",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "19.0.0-rc-6230622a1a-20240610",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-canary.53",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "19.0.0-rc-6230622a1a-20240610",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
2
templates/website/.gitignore
vendored
2
templates/website/.gitignore
vendored
@@ -7,4 +7,4 @@ node_modules
|
||||
.vercel
|
||||
|
||||
# Payload default media upload directory
|
||||
./public/media
|
||||
public/media/
|
||||
|
||||
@@ -5,24 +5,19 @@
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"dev": "next dev --turbo",
|
||||
"dev:prod": "rm -rf .next && pnpm build && pnpm serve",
|
||||
"generate:types": "payload generate:types",
|
||||
"ii": "pnpm --ignore-workspace install",
|
||||
"lint": "next lint",
|
||||
"lint:fix": "next lint --fix",
|
||||
"payload": "payload",
|
||||
"reinstall": "rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install",
|
||||
"start": "next start"
|
||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"dev:prod": "cross-env NODE_OPTIONS=--no-deprecation rm -rf .next && pnpm build && pnpm serve",
|
||||
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
|
||||
"ii": "cross-env NODE_OPTIONS=--no-deprecation pnpm --ignore-workspace install",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lexical/list": "0.16.1",
|
||||
"@lexical/react": "0.16.1",
|
||||
"@lexical/rich-text": "0.16.1",
|
||||
"@lexical/utils": "0.16.1",
|
||||
"@payloadcms/db-mongodb": "3.0.0-beta.63",
|
||||
"@payloadcms/db-postgres": "3.0.0-beta.63",
|
||||
"@payloadcms/live-preview-react": "3.0.0-beta.63",
|
||||
"@payloadcms/next": "3.0.0-beta.63",
|
||||
"@payloadcms/plugin-cloud": "3.0.0-beta.63",
|
||||
@@ -39,8 +34,6 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "^8.2.0",
|
||||
"escape-html": "^1.0.3",
|
||||
"geist": "^1.3.0",
|
||||
"graphql": "^16.8.1",
|
||||
"jsonwebtoken": "9.0.1",
|
||||
@@ -50,11 +43,9 @@
|
||||
"payload": "3.0.0-beta.63",
|
||||
"payload-admin-bar": "^1.0.6",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"qs": "6.11.2",
|
||||
"react": "beta",
|
||||
"react-dom": "beta",
|
||||
"react": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-hook-form": "7.45.4",
|
||||
"react-router-dom": "5.3.4",
|
||||
"sharp": "0.32.6",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
@@ -65,8 +56,8 @@
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@types/escape-html": "^1.0.2",
|
||||
"@types/node": "18.11.3",
|
||||
"@types/qs": "^6.9.8",
|
||||
"@types/react": "^18.3.0",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"copyfiles": "^2.4.1",
|
||||
"eslint": "^8",
|
||||
@@ -79,7 +70,14 @@
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.9.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@types/react": "npm:types-react@19.0.0-rc.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0"
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"@types/react": "18.2.74"
|
||||
"@types/react": "npm:types-react@19.0.0-rc.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0"
|
||||
}
|
||||
}
|
||||
|
||||
1994
templates/website/pnpm-lock.yaml
generated
1994
templates/website/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -19,15 +19,11 @@ export const RelatedPosts: React.FC<RelatedPostsProps> = (props) => {
|
||||
<div className={clsx('container', className)}>
|
||||
{introContent && <RichText content={introContent} enableGutter={false} />}
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-8 items-stretch">
|
||||
{docs?.map((doc, index) => {
|
||||
if (typeof doc === 'string') return null
|
||||
|
||||
return (
|
||||
<div key={index}>
|
||||
<Card doc={doc} relationTo="posts" showCategories />
|
||||
</div>
|
||||
)
|
||||
return <Card key={index} doc={doc} relationTo="posts" showCategories />
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -223,8 +223,8 @@ export interface Page {
|
||||
)[];
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
image?: string | Media | null;
|
||||
description?: string | null;
|
||||
};
|
||||
publishedAt?: string | null;
|
||||
slug?: string | null;
|
||||
@@ -272,7 +272,7 @@ export interface Media {
|
||||
*/
|
||||
export interface Category {
|
||||
id: string;
|
||||
title?: string | null;
|
||||
title: string;
|
||||
parent?: (string | null) | Category;
|
||||
breadcrumbs?:
|
||||
| {
|
||||
@@ -291,6 +291,7 @@ export interface Category {
|
||||
*/
|
||||
export interface Post {
|
||||
id: string;
|
||||
title: string;
|
||||
content: {
|
||||
root: {
|
||||
type: string;
|
||||
@@ -310,10 +311,9 @@ export interface Post {
|
||||
categories?: (string | Category)[] | null;
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
image?: string | Media | null;
|
||||
description?: string | null;
|
||||
};
|
||||
title: string;
|
||||
publishedAt?: string | null;
|
||||
authors?: (string | User)[] | null;
|
||||
populatedAuthors?:
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
} from '@payloadcms/richtext-lexical'
|
||||
import sharp from 'sharp' // editor-import
|
||||
import { UnderlineFeature } from '@payloadcms/richtext-lexical'
|
||||
import dotenv from 'dotenv'
|
||||
import path from 'path'
|
||||
import { buildConfig } from 'payload'
|
||||
import { fileURLToPath } from 'url'
|
||||
@@ -32,17 +31,21 @@ import { seed } from './payload/endpoints/seed'
|
||||
import { Footer } from './payload/globals/Footer/Footer'
|
||||
import { Header } from './payload/globals/Header/Header'
|
||||
import { revalidateRedirects } from './payload/hooks/revalidateRedirects'
|
||||
import { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
|
||||
import { Page, Post } from 'src/payload-types'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
const generateTitle = () => {
|
||||
return 'My Website'
|
||||
const generateTitle: GenerateTitle<Post | Page> = ({ doc }) => {
|
||||
return doc?.title ? `${doc.title} | Payload Website Template` : 'Payload Website Template'
|
||||
}
|
||||
|
||||
dotenv.config({
|
||||
path: path.resolve(dirname, '../../.env'),
|
||||
})
|
||||
const generateURL: GenerateURL<Post | Page> = ({ doc }) => {
|
||||
return doc?.slug
|
||||
? `${process.env.NEXT_PUBLIC_SERVER_URL}/${doc.slug}`
|
||||
: process.env.NEXT_PUBLIC_SERVER_URL
|
||||
}
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
@@ -133,10 +136,8 @@ export default buildConfig({
|
||||
collections: ['categories'],
|
||||
}),
|
||||
seoPlugin({
|
||||
collections: ['pages', 'posts'],
|
||||
generateTitle,
|
||||
tabbedUI: true,
|
||||
uploadsCollection: 'media',
|
||||
generateURL,
|
||||
}),
|
||||
formBuilderPlugin({
|
||||
fields: {
|
||||
|
||||
@@ -18,6 +18,7 @@ const Categories: CollectionConfig = {
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export const Media: CollectionConfig = {
|
||||
},
|
||||
],
|
||||
upload: {
|
||||
staticDir: path.resolve(dirname, '../../public/media'),
|
||||
// Upload to the public/media directory in Next.js making them publicly accessible even outside of Payload
|
||||
staticDir: path.resolve(dirname, '../../../public/media'),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -13,6 +13,13 @@ import { populatePublishedAt } from '../../hooks/populatePublishedAt'
|
||||
import { generatePreviewPath } from '../../utilities/generatePreviewPath'
|
||||
import { revalidatePage } from './hooks/revalidatePage'
|
||||
|
||||
import {
|
||||
MetaDescriptionField,
|
||||
MetaImageField,
|
||||
MetaTitleField,
|
||||
OverviewField,
|
||||
PreviewField,
|
||||
} from '@payloadcms/plugin-seo/fields'
|
||||
export const Pages: CollectionConfig = {
|
||||
slug: 'pages',
|
||||
access: {
|
||||
@@ -36,18 +43,16 @@ export const Pages: CollectionConfig = {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
hero,
|
||||
],
|
||||
fields: [hero],
|
||||
label: 'Hero',
|
||||
},
|
||||
{
|
||||
@@ -61,6 +66,33 @@ export const Pages: CollectionConfig = {
|
||||
],
|
||||
label: 'Content',
|
||||
},
|
||||
{
|
||||
name: 'meta',
|
||||
label: 'SEO',
|
||||
fields: [
|
||||
OverviewField({
|
||||
titlePath: 'meta.title',
|
||||
descriptionPath: 'meta.description',
|
||||
imagePath: 'meta.image',
|
||||
}),
|
||||
MetaTitleField({
|
||||
hasGenerateFn: true,
|
||||
}),
|
||||
MetaImageField({
|
||||
relationTo: 'media',
|
||||
}),
|
||||
|
||||
MetaDescriptionField({}),
|
||||
PreviewField({
|
||||
// if the `generateUrl` function is configured
|
||||
hasGenerateFn: true,
|
||||
|
||||
// field paths to match the target field for data
|
||||
titlePath: 'meta.title',
|
||||
descriptionPath: 'meta.description',
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -79,7 +111,7 @@ export const Pages: CollectionConfig = {
|
||||
versions: {
|
||||
drafts: {
|
||||
autosave: {
|
||||
interval: 350, // We set this interval for optimal live preview
|
||||
interval: 100, // We set this interval for optimal live preview
|
||||
},
|
||||
},
|
||||
maxPerDoc: 50,
|
||||
|
||||
@@ -4,18 +4,20 @@ import type { CollectionAfterReadHook } from 'payload'
|
||||
// This means that we need to populate the authors manually here to protect user privacy
|
||||
// GraphQL will not return mutated user data that differs from the underlying schema
|
||||
// So we use an alternative `populatedAuthors` field to populate the user data, hidden from the admin UI
|
||||
export const populateAuthors: CollectionAfterReadHook = async ({ doc, req: { payload } }) => {
|
||||
export const populateAuthors: CollectionAfterReadHook = async ({ doc, req, req: { payload } }) => {
|
||||
if (doc?.authors) {
|
||||
const authorDocs = await Promise.all(
|
||||
doc.authors.map(
|
||||
async (author) =>
|
||||
await payload.findByID({
|
||||
id: typeof author === 'object' ? author?.id : author,
|
||||
collection: 'users',
|
||||
depth: 0,
|
||||
}),
|
||||
),
|
||||
)
|
||||
const authorDocs = []
|
||||
|
||||
for (const author of doc.authors) {
|
||||
const authorDoc = await payload.findByID({
|
||||
id: typeof author === 'object' ? author?.id : author,
|
||||
collection: 'users',
|
||||
depth: 0,
|
||||
req,
|
||||
})
|
||||
|
||||
authorDocs.push(authorDoc)
|
||||
}
|
||||
|
||||
doc.populatedAuthors = authorDocs.map((authorDoc) => ({
|
||||
id: authorDoc.id,
|
||||
|
||||
@@ -19,6 +19,14 @@ import { generatePreviewPath } from '../../utilities/generatePreviewPath'
|
||||
import { populateAuthors } from './hooks/populateAuthors'
|
||||
import { revalidatePost } from './hooks/revalidatePost'
|
||||
|
||||
import {
|
||||
MetaDescriptionField,
|
||||
MetaImageField,
|
||||
MetaTitleField,
|
||||
OverviewField,
|
||||
PreviewField,
|
||||
} from '@payloadcms/plugin-seo/fields'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
access: {
|
||||
@@ -42,6 +50,11 @@ export const Posts: CollectionConfig = {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
@@ -98,16 +111,35 @@ export const Posts: CollectionConfig = {
|
||||
],
|
||||
label: 'Meta',
|
||||
},
|
||||
{
|
||||
name: 'meta',
|
||||
label: 'SEO',
|
||||
fields: [
|
||||
OverviewField({
|
||||
titlePath: 'meta.title',
|
||||
descriptionPath: 'meta.description',
|
||||
imagePath: 'meta.image',
|
||||
}),
|
||||
MetaTitleField({
|
||||
hasGenerateFn: true,
|
||||
}),
|
||||
MetaImageField({
|
||||
relationTo: 'media',
|
||||
}),
|
||||
|
||||
MetaDescriptionField({}),
|
||||
PreviewField({
|
||||
// if the `generateUrl` function is configured
|
||||
hasGenerateFn: true,
|
||||
|
||||
// field paths to match the target field for data
|
||||
titlePath: 'meta.title',
|
||||
descriptionPath: 'meta.description',
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'publishedAt',
|
||||
type: 'date',
|
||||
@@ -169,7 +201,9 @@ export const Posts: CollectionConfig = {
|
||||
},
|
||||
versions: {
|
||||
drafts: {
|
||||
autosave: true,
|
||||
autosave: {
|
||||
interval: 100, // We set this interval for optimal live preview
|
||||
},
|
||||
},
|
||||
maxPerDoc: 50,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import { toast } from '@payloadcms/ui'
|
||||
|
||||
const SuccessMessage: React.FC = () => (
|
||||
<div>
|
||||
Database seeded! You can now{' '}
|
||||
<a target="_blank" href="/">
|
||||
visit your website
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const SeedButton: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false)
|
||||
@@ -17,6 +27,7 @@ export const SeedButton: React.FC = () => {
|
||||
try {
|
||||
await fetch('/api/seed')
|
||||
setSeeded(true)
|
||||
toast.success(<SuccessMessage />, { duration: 5000 })
|
||||
} catch (err) {
|
||||
setError(err)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ const BeforeDashboard: React.FC = () => {
|
||||
<li>
|
||||
<SeedButton />
|
||||
{' with a few pages, posts, and projects to jump-start your new site, then '}
|
||||
<a href="/">visit your website</a>
|
||||
<a href="/" target="_blank">
|
||||
visit your website
|
||||
</a>
|
||||
{' to see the results.'}
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -10,9 +10,14 @@ export const seed: PayloadHandler = async (req): Promise<Response> => {
|
||||
}
|
||||
|
||||
try {
|
||||
// Create a transaction so that all seeding happens in one transaction
|
||||
await initTransaction(req)
|
||||
|
||||
await seedScript({ payload, req })
|
||||
|
||||
// Finalise transactiojn
|
||||
await commitTransaction(req)
|
||||
|
||||
return Response.json({ success: true })
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
|
||||
@@ -10,6 +10,7 @@ export const contact: Partial<Page> = {
|
||||
{
|
||||
blockType: 'formBlock',
|
||||
enableIntro: true,
|
||||
// @ts-ignore
|
||||
form: '{{CONTACT_FORM_ID}}',
|
||||
introContent: {
|
||||
root: {
|
||||
|
||||
@@ -80,552 +80,6 @@ export const homeStatic: Page = {
|
||||
},
|
||||
},
|
||||
},
|
||||
/* layout: [
|
||||
{
|
||||
blockName: 'Content Block',
|
||||
blockType: 'content',
|
||||
columns: [
|
||||
{
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Core features',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h2',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
size: 'full',
|
||||
},
|
||||
{
|
||||
enableLink: false,
|
||||
link: {
|
||||
label: '',
|
||||
reference: null,
|
||||
url: '',
|
||||
},
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Admin Dashboard',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: "Manage this site's pages and posts from the ",
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'admin dashboard',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
fields: {
|
||||
linkType: 'custom',
|
||||
newTab: false,
|
||||
url: '/admin',
|
||||
},
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 2,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
size: 'oneThird',
|
||||
},
|
||||
{
|
||||
enableLink: false,
|
||||
link: {
|
||||
label: '',
|
||||
reference: null,
|
||||
url: '',
|
||||
},
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Preview',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Using versions, drafts, and preview, editors can review and share their changes before publishing them.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
size: 'oneThird',
|
||||
},
|
||||
{
|
||||
enableLink: false,
|
||||
link: {
|
||||
label: '',
|
||||
reference: null,
|
||||
url: '',
|
||||
},
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Page Builder',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Custom page builder allows you to create unique page, post, and project layouts for any type of content.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
size: 'oneThird',
|
||||
},
|
||||
{
|
||||
enableLink: false,
|
||||
link: {
|
||||
label: '',
|
||||
reference: null,
|
||||
url: '',
|
||||
},
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'SEO',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Editors have complete control over SEO data and site content directly from the ',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'admin dashboard',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
fields: {
|
||||
linkType: 'custom',
|
||||
newTab: false,
|
||||
url: '/admin',
|
||||
},
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 2,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
size: 'oneThird',
|
||||
},
|
||||
{
|
||||
enableLink: false,
|
||||
link: {
|
||||
label: '',
|
||||
reference: null,
|
||||
url: '',
|
||||
},
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Dark Mode',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Users will experience this site in their preferred color scheme and each block can be inverted.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
size: 'oneThird',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
blockName: 'Archive Block',
|
||||
blockType: 'archive',
|
||||
categories: [],
|
||||
introContent: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Recent posts',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'The posts below are displayed in an "Archive" layout building block which is an extremely powerful way to display documents on a page. It can be auto-populated by collection or by category, or posts can be individually selected. Pagination controls will automatically appear if the number of results exceeds the number of items per page.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
populateBy: 'collection',
|
||||
relationTo: 'posts',
|
||||
},
|
||||
{
|
||||
blockName: 'CTA',
|
||||
blockType: 'cta',
|
||||
links: [
|
||||
{
|
||||
link: {
|
||||
type: 'custom',
|
||||
appearance: 'default',
|
||||
label: 'All posts',
|
||||
url: '/posts',
|
||||
},
|
||||
},
|
||||
],
|
||||
richText: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'This is a call to action',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h3',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'This is a custom layout building block ',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'configured in the admin dashboard',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
fields: {
|
||||
linkType: 'custom',
|
||||
newTab: false,
|
||||
url: '/admin',
|
||||
},
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 2,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
], */
|
||||
meta: {
|
||||
description: 'An open-source website built with Payload and Next.js.',
|
||||
title: 'Payload Website Template',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Page } from '../../payload-types'
|
||||
import type { RequiredDataFromCollectionSlug } from 'payload'
|
||||
|
||||
export const home: Partial<Page> = {
|
||||
export const home: RequiredDataFromCollectionSlug<'pages'> = {
|
||||
slug: 'home',
|
||||
_status: 'published',
|
||||
hero: {
|
||||
@@ -23,6 +23,7 @@ export const home: Partial<Page> = {
|
||||
},
|
||||
},
|
||||
],
|
||||
// @ts-ignore
|
||||
media: '{{IMAGE_1}}',
|
||||
richText: {
|
||||
root: {
|
||||
@@ -501,6 +502,7 @@ export const home: Partial<Page> = {
|
||||
{
|
||||
blockName: 'Media Block',
|
||||
blockType: 'mediaBlock',
|
||||
// @ts-ignore
|
||||
media: '{{IMAGE_2}}',
|
||||
position: 'default',
|
||||
},
|
||||
@@ -658,6 +660,7 @@ export const home: Partial<Page> = {
|
||||
],
|
||||
meta: {
|
||||
description: 'An open-source website built with Payload and Next.js.',
|
||||
// @ts-ignore
|
||||
image: '{{IMAGE_1}}',
|
||||
title: 'Payload Website Template',
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Payload, PayloadRequest } from 'payload'
|
||||
import type { CollectionSlug, GlobalSlug, Payload, PayloadRequest } from 'payload'
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
@@ -12,12 +12,20 @@ import { image2 } from './image-2'
|
||||
import { post1 } from './post-1'
|
||||
import { post2 } from './post-2'
|
||||
import { post3 } from './post-3'
|
||||
import { exists } from 'fs-extra'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
const collections = ['categories', 'media', 'pages', 'posts', 'forms', 'form-submissions']
|
||||
const globals = ['header', 'footer']
|
||||
const collections: CollectionSlug[] = [
|
||||
'categories',
|
||||
'media',
|
||||
'pages',
|
||||
'posts',
|
||||
'forms',
|
||||
'form-submissions',
|
||||
]
|
||||
const globals: GlobalSlug[] = ['header', 'footer']
|
||||
|
||||
// Next.js revalidation errors are normal when seeding the database without a server running
|
||||
// i.e. running `yarn seed` locally instead of using the admin UI within an active app
|
||||
@@ -47,133 +55,140 @@ export const seed = async ({
|
||||
payload.logger.info(`— Clearing collections and globals...`)
|
||||
|
||||
// clear the database
|
||||
await Promise.all([
|
||||
...collections.map((collection) =>
|
||||
payload.delete({
|
||||
collection: collection as 'media',
|
||||
req,
|
||||
where: {},
|
||||
}),
|
||||
),
|
||||
...globals.map((global) =>
|
||||
payload.updateGlobal({
|
||||
slug: global as 'header',
|
||||
data: {},
|
||||
req,
|
||||
}),
|
||||
),
|
||||
])
|
||||
for (const global of globals) {
|
||||
await payload.updateGlobal({
|
||||
slug: global,
|
||||
data: {
|
||||
navItems: [],
|
||||
},
|
||||
req,
|
||||
})
|
||||
}
|
||||
|
||||
for (const collection of collections) {
|
||||
console.log('delete', collection)
|
||||
await payload.delete({
|
||||
collection: collection,
|
||||
where: {
|
||||
id: {
|
||||
exists: true,
|
||||
},
|
||||
},
|
||||
req,
|
||||
})
|
||||
}
|
||||
|
||||
const pages = await payload.delete({
|
||||
collection: 'pages',
|
||||
where: {},
|
||||
req,
|
||||
})
|
||||
|
||||
console.log({ pages })
|
||||
|
||||
payload.logger.info(`— Seeding demo author and user...`)
|
||||
|
||||
await Promise.all(
|
||||
['demo-author@payloadcms.com'].map(async (email) => {
|
||||
await payload.delete({
|
||||
collection: 'users',
|
||||
req,
|
||||
where: {
|
||||
email: {
|
||||
equals: email,
|
||||
},
|
||||
},
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const [demoAuthor] = await Promise.all([
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
name: 'Demo Author',
|
||||
email: 'demo-author@payloadcms.com',
|
||||
password: 'password',
|
||||
await payload.delete({
|
||||
collection: 'users',
|
||||
where: {
|
||||
email: {
|
||||
equals: 'demo-author@payloadcms.com',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
])
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
let demoAuthorID = demoAuthor.id
|
||||
const demoAuthor = await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
name: 'Demo Author',
|
||||
email: 'demo-author@payloadcms.com',
|
||||
password: 'password',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
let demoAuthorID: number | string = demoAuthor.id
|
||||
|
||||
payload.logger.info(`— Seeding media...`)
|
||||
|
||||
const [image1Doc, image2Doc, image3Doc, imageHomeDoc] = await Promise.all([
|
||||
await payload.create({
|
||||
collection: 'media',
|
||||
data: image1,
|
||||
filePath: path.resolve(dirname, 'image-post1.webp'),
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'media',
|
||||
data: image2,
|
||||
filePath: path.resolve(dirname, 'image-post2.webp'),
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'media',
|
||||
data: image2,
|
||||
filePath: path.resolve(dirname, 'image-post3.webp'),
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'media',
|
||||
data: image2,
|
||||
filePath: path.resolve(dirname, 'image-hero1.webp'),
|
||||
req,
|
||||
}),
|
||||
])
|
||||
const image1Doc = await payload.create({
|
||||
collection: 'media',
|
||||
data: image1,
|
||||
filePath: path.resolve(dirname, 'image-post1.webp'),
|
||||
req,
|
||||
})
|
||||
const image2Doc = await payload.create({
|
||||
collection: 'media',
|
||||
data: image2,
|
||||
filePath: path.resolve(dirname, 'image-post2.webp'),
|
||||
req,
|
||||
})
|
||||
const image3Doc = await payload.create({
|
||||
collection: 'media',
|
||||
data: image2,
|
||||
filePath: path.resolve(dirname, 'image-post3.webp'),
|
||||
req,
|
||||
})
|
||||
const imageHomeDoc = await payload.create({
|
||||
collection: 'media',
|
||||
data: image2,
|
||||
filePath: path.resolve(dirname, 'image-hero1.webp'),
|
||||
req,
|
||||
})
|
||||
|
||||
payload.logger.info(`— Seeding categories...`)
|
||||
const technologyCategory = await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Technology',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
const [technologyCategory, newsCategory, financeCategory] = await Promise.all([
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Technology',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'News',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Finance',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Design',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Software',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Engineering',
|
||||
},
|
||||
req,
|
||||
}),
|
||||
])
|
||||
const newsCategory = await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'News',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
let image1ID = image1Doc.id
|
||||
let image2ID = image2Doc.id
|
||||
let image3ID = image3Doc.id
|
||||
let imageHomeID = imageHomeDoc.id
|
||||
const financeCategory = await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Finance',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Design',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Software',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'categories',
|
||||
data: {
|
||||
title: 'Engineering',
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
let image1ID: number | string = image1Doc.id
|
||||
let image2ID: number | string = image2Doc.id
|
||||
let image3ID: number | string = image3Doc.id
|
||||
let imageHomeID: number | string = imageHomeDoc.id
|
||||
|
||||
if (payload.db.defaultIDType === 'text') {
|
||||
image1ID = `"${image1Doc.id}"`
|
||||
@@ -191,9 +206,9 @@ export const seed = async ({
|
||||
collection: 'posts',
|
||||
data: JSON.parse(
|
||||
JSON.stringify({ ...post1, categories: [technologyCategory.id] })
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, image1ID)
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, image2ID)
|
||||
.replace(/"\{\{AUTHOR\}\}"/g, demoAuthorID),
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, String(image1ID))
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, String(image2ID))
|
||||
.replace(/"\{\{AUTHOR\}\}"/g, String(demoAuthorID)),
|
||||
),
|
||||
req,
|
||||
})
|
||||
@@ -202,9 +217,9 @@ export const seed = async ({
|
||||
collection: 'posts',
|
||||
data: JSON.parse(
|
||||
JSON.stringify({ ...post2, categories: [newsCategory.id] })
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, image2ID)
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, image3ID)
|
||||
.replace(/"\{\{AUTHOR\}\}"/g, demoAuthorID),
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, String(image2ID))
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, String(image3ID))
|
||||
.replace(/"\{\{AUTHOR\}\}"/g, String(demoAuthorID)),
|
||||
),
|
||||
req,
|
||||
})
|
||||
@@ -213,41 +228,38 @@ export const seed = async ({
|
||||
collection: 'posts',
|
||||
data: JSON.parse(
|
||||
JSON.stringify({ ...post3, categories: [financeCategory.id] })
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, image3ID)
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, image1ID)
|
||||
.replace(/"\{\{AUTHOR\}\}"/g, demoAuthorID),
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, String(image3ID))
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, String(image1ID))
|
||||
.replace(/"\{\{AUTHOR\}\}"/g, String(demoAuthorID)),
|
||||
),
|
||||
req,
|
||||
})
|
||||
|
||||
// update each post with related posts
|
||||
|
||||
await Promise.all([
|
||||
await payload.update({
|
||||
id: post1Doc.id,
|
||||
collection: 'posts',
|
||||
data: {
|
||||
relatedPosts: [post2Doc.id, post3Doc.id],
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.update({
|
||||
id: post2Doc.id,
|
||||
collection: 'posts',
|
||||
data: {
|
||||
relatedPosts: [post1Doc.id, post3Doc.id],
|
||||
},
|
||||
req,
|
||||
}),
|
||||
await payload.update({
|
||||
id: post3Doc.id,
|
||||
collection: 'posts',
|
||||
data: {
|
||||
relatedPosts: [post1Doc.id, post2Doc.id],
|
||||
},
|
||||
req,
|
||||
}),
|
||||
])
|
||||
await payload.update({
|
||||
id: post1Doc.id,
|
||||
collection: 'posts',
|
||||
data: {
|
||||
relatedPosts: [post2Doc.id, post3Doc.id],
|
||||
},
|
||||
req,
|
||||
})
|
||||
await payload.update({
|
||||
id: post2Doc.id,
|
||||
collection: 'posts',
|
||||
data: {
|
||||
relatedPosts: [post1Doc.id, post3Doc.id],
|
||||
},
|
||||
req,
|
||||
})
|
||||
await payload.update({
|
||||
id: post3Doc.id,
|
||||
collection: 'posts',
|
||||
data: {
|
||||
relatedPosts: [post1Doc.id, post2Doc.id],
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
payload.logger.info(`— Seeding home page...`)
|
||||
|
||||
@@ -255,8 +267,8 @@ export const seed = async ({
|
||||
collection: 'pages',
|
||||
data: JSON.parse(
|
||||
JSON.stringify(home)
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, imageHomeID)
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, image2ID),
|
||||
.replace(/"\{\{IMAGE_1\}\}"/g, String(imageHomeID))
|
||||
.replace(/"\{\{IMAGE_2\}\}"/g, String(image2ID)),
|
||||
),
|
||||
req,
|
||||
})
|
||||
@@ -269,7 +281,7 @@ export const seed = async ({
|
||||
req,
|
||||
})
|
||||
|
||||
let contactFormID = contactForm.id
|
||||
let contactFormID: number | string = contactForm.id
|
||||
|
||||
if (payload.db.defaultIDType === 'text') {
|
||||
contactFormID = `"${contactFormID}"`
|
||||
@@ -280,7 +292,7 @@ export const seed = async ({
|
||||
const contactPage = await payload.create({
|
||||
collection: 'pages',
|
||||
data: JSON.parse(
|
||||
JSON.stringify(contactPageData).replace(/"\{\{CONTACT_FORM_ID\}\}"/g, contactFormID),
|
||||
JSON.stringify(contactPageData).replace(/"\{\{CONTACT_FORM_ID\}\}"/g, String(contactFormID)),
|
||||
),
|
||||
req,
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Post } from '../../payload-types'
|
||||
export const post1: Partial<Post> = {
|
||||
slug: 'digital-horizons',
|
||||
_status: 'published',
|
||||
// @ts-ignore
|
||||
authors: ['{{AUTHOR}}'],
|
||||
content: {
|
||||
root: {
|
||||
@@ -295,6 +296,7 @@ export const post1: Partial<Post> = {
|
||||
meta: {
|
||||
description:
|
||||
'Dive into the marvels of modern innovation, where the only constant is change. A journey where pixels and data converge to craft the future.',
|
||||
// @ts-ignore
|
||||
image: '{{IMAGE_1}}',
|
||||
title: 'Digital Horizons: A Glimpse into Tomorrow',
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Post } from '../../payload-types'
|
||||
export const post2: Partial<Post> = {
|
||||
slug: 'global-gaze',
|
||||
_status: 'published',
|
||||
// @ts-ignore
|
||||
authors: ['{{AUTHOR}}'],
|
||||
content: {
|
||||
root: {
|
||||
@@ -217,6 +218,7 @@ export const post2: Partial<Post> = {
|
||||
meta: {
|
||||
description:
|
||||
'Explore the untold and overlooked. A magnified view into the corners of the world, where every story deserves its spotlight.',
|
||||
// @ts-ignore
|
||||
image: '{{IMAGE_1}}',
|
||||
title: 'Global Gaze: Beyond the Headlines',
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Post } from '../../payload-types'
|
||||
export const post3: Partial<Post> = {
|
||||
slug: 'dollar-and-sense-the-financial-forecast',
|
||||
_status: 'published',
|
||||
// @ts-ignore
|
||||
authors: ['{{AUTHOR}}'],
|
||||
content: {
|
||||
root: {
|
||||
@@ -253,6 +254,7 @@ export const post3: Partial<Post> = {
|
||||
},
|
||||
meta: {
|
||||
description: `Money isn't just currency; it's a language. Dive deep into its nuances, where strategy meets intuition in the vast sea of finance.`,
|
||||
// @ts-ignore
|
||||
image: '{{IMAGE_1}}',
|
||||
title: 'Dollar and Sense: The Financial Forecast',
|
||||
},
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"target": "es6",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
@@ -22,15 +26,25 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@payload-config": ["./src/payload.config.ts"],
|
||||
"react": ["./node_modules/@types/react"],
|
||||
"@/*": ["./src/app/*"]
|
||||
"@payload-config": [
|
||||
"./src/payload.config.ts"
|
||||
],
|
||||
"react": [
|
||||
"./node_modules/@types/react"
|
||||
],
|
||||
"@/*": [
|
||||
"./src/app/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "redirects.js", "next.config.js"],
|
||||
"exclude": ["node_modules"],
|
||||
"ts-node": {
|
||||
"transpileOnly": true,
|
||||
"swc": true
|
||||
}
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"redirects.js",
|
||||
"next.config.js"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-canary.53",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "19.0.0-rc-6230622a1a-20240610",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-canary.53",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "^19.0.0-rc-6230622a1a-20240610"
|
||||
"react": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "19.0.0-rc-6230622a1a-20240610"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.9",
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-canary.53",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "^19.0.0-rc-6230622a1a-20240610"
|
||||
"react": "19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "19.0.0-rc-6230622a1a-20240610"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.9",
|
||||
|
||||
Reference in New Issue
Block a user