added SEO and nav
This commit is contained in:
3
bun.lock
3
bun.lock
@@ -7,6 +7,7 @@
|
||||
"@payloadcms/db-postgres": "3.59.1",
|
||||
"@payloadcms/next": "3.59.1",
|
||||
"@payloadcms/payload-cloud": "3.59.1",
|
||||
"@payloadcms/plugin-seo": "^3.59.1",
|
||||
"@payloadcms/richtext-lexical": "3.59.1",
|
||||
"@payloadcms/ui": "3.59.1",
|
||||
"cross-env": "^7.0.3",
|
||||
@@ -471,6 +472,8 @@
|
||||
|
||||
"@payloadcms/payload-cloud": ["@payloadcms/payload-cloud@3.59.1", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "^3.614.0", "@aws-sdk/client-s3": "^3.614.0", "@aws-sdk/credential-providers": "^3.614.0", "@aws-sdk/lib-storage": "^3.614.0", "@payloadcms/email-nodemailer": "3.59.1", "amazon-cognito-identity-js": "^6.1.2", "nodemailer": "6.9.16" }, "peerDependencies": { "payload": "3.59.1" } }, "sha512-ZuP7ZPsu+GE4+07a1wrs/EaLQBhoA4Ij0en9YL+qHWAiLCPo8NF2L4cSdWrN+XKKA6G53gqLBaLotCJ8veR6uA=="],
|
||||
|
||||
"@payloadcms/plugin-seo": ["@payloadcms/plugin-seo@3.59.1", "", { "dependencies": { "@payloadcms/translations": "3.59.1", "@payloadcms/ui": "3.59.1" }, "peerDependencies": { "payload": "3.59.1", "react": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020", "react-dom": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020" } }, "sha512-Dc/tR/Vx+sprsY8lQhf/MdCasCY7B5ScTJfAgaYf00rQqY2Y1L8zFtg0tuwOIgtSXvRh/GbRS3+vZcPldagHIA=="],
|
||||
|
||||
"@payloadcms/richtext-lexical": ["@payloadcms/richtext-lexical@3.59.1", "", { "dependencies": { "@lexical/headless": "0.35.0", "@lexical/html": "0.35.0", "@lexical/link": "0.35.0", "@lexical/list": "0.35.0", "@lexical/mark": "0.35.0", "@lexical/react": "0.35.0", "@lexical/rich-text": "0.35.0", "@lexical/selection": "0.35.0", "@lexical/table": "0.35.0", "@lexical/utils": "0.35.0", "@payloadcms/translations": "3.59.1", "@payloadcms/ui": "3.59.1", "@types/uuid": "10.0.0", "acorn": "8.12.1", "bson-objectid": "2.0.4", "csstype": "3.1.3", "dequal": "2.0.3", "escape-html": "1.0.3", "jsox": "1.2.121", "lexical": "0.35.0", "mdast-util-from-markdown": "2.0.2", "mdast-util-mdx-jsx": "3.1.3", "micromark-extension-mdx-jsx": "3.0.1", "qs-esm": "7.0.2", "react-error-boundary": "4.1.2", "ts-essentials": "10.0.3", "uuid": "10.0.0" }, "peerDependencies": { "@faceless-ui/modal": "3.0.0", "@faceless-ui/scroll-info": "2.0.0", "@payloadcms/next": "3.59.1", "payload": "3.59.1", "react": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020", "react-dom": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020" } }, "sha512-bVuLAnOxR1kL8IYD5iD269eO47ptX9/dxR2mFbJCYyG5qWFSU9gH3ocgJc/vVcU4SmghFADIxQzrpinPYmtveQ=="],
|
||||
|
||||
"@payloadcms/translations": ["@payloadcms/translations@3.59.1", "", { "dependencies": { "date-fns": "4.1.0" } }, "sha512-kBuYV4tGOUpVkh6es6cBhbJn14dGtNnYkGtHhScbtGVX6ZJyVudY9ypKQhljAEzdQq0n+kkmi1sfwlaRps+t6w=="],
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"@payloadcms/db-postgres": "3.59.1",
|
||||
"@payloadcms/next": "3.59.1",
|
||||
"@payloadcms/payload-cloud": "3.59.1",
|
||||
"@payloadcms/plugin-seo": "^3.59.1",
|
||||
"@payloadcms/richtext-lexical": "3.59.1",
|
||||
"@payloadcms/ui": "3.59.1",
|
||||
"cross-env": "^7.0.3",
|
||||
|
||||
@@ -22,6 +22,11 @@ import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93
|
||||
import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
||||
import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
||||
import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
||||
import { OverviewComponent as OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860 } from '@payloadcms/plugin-seo/client'
|
||||
import { MetaTitleComponent as MetaTitleComponent_a8a977ebc872c5d5ea7ee689724c0860 } from '@payloadcms/plugin-seo/client'
|
||||
import { MetaImageComponent as MetaImageComponent_a8a977ebc872c5d5ea7ee689724c0860 } from '@payloadcms/plugin-seo/client'
|
||||
import { MetaDescriptionComponent as MetaDescriptionComponent_a8a977ebc872c5d5ea7ee689724c0860 } from '@payloadcms/plugin-seo/client'
|
||||
import { PreviewComponent as PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860 } from '@payloadcms/plugin-seo/client'
|
||||
import { SlugField as SlugField_3817bf644402e67bfe6577f60ef982de } from '@payloadcms/ui'
|
||||
|
||||
export const importMap = {
|
||||
@@ -49,5 +54,10 @@ export const importMap = {
|
||||
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
"@payloadcms/plugin-seo/client#MetaTitleComponent": MetaTitleComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
"@payloadcms/plugin-seo/client#MetaImageComponent": MetaImageComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
"@payloadcms/plugin-seo/client#MetaDescriptionComponent": MetaDescriptionComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
"@payloadcms/plugin-seo/client#PreviewComponent": PreviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
|
||||
"@payloadcms/ui#SlugField": SlugField_3817bf644402e67bfe6577f60ef982de
|
||||
}
|
||||
|
||||
22
src/collections/Nav/index.ts
Normal file
22
src/collections/Nav/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { GlobalConfig } from 'payload';
|
||||
|
||||
export const Nav: GlobalConfig = {
|
||||
slug: 'nav',
|
||||
label: 'Navigation',
|
||||
fields: [
|
||||
{
|
||||
name: 'items',
|
||||
type: 'array',
|
||||
required: true,
|
||||
maxRows: 8,
|
||||
fields: [
|
||||
{
|
||||
name: 'page',
|
||||
type: 'relationship',
|
||||
relationTo: 'pages',
|
||||
required: true,
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MetaDescriptionField, MetaImageField, MetaTitleField, OverviewField, PreviewField } from '@payloadcms/plugin-seo/fields'
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { slugField } from 'payload'
|
||||
|
||||
@@ -17,9 +18,48 @@ export const Page: CollectionConfig = {
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'richText',
|
||||
type: 'richText'
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
label: 'Content',
|
||||
fields: [
|
||||
{
|
||||
name: 'richText',
|
||||
type: 'richText'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
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',
|
||||
}),
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
slugField(),
|
||||
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { slugField } from 'payload'
|
||||
import { fa } from 'payload/i18n/fa'
|
||||
|
||||
export const Projects: CollectionConfig = {
|
||||
slug: 'projects',
|
||||
@@ -72,7 +71,7 @@ export const Projects: CollectionConfig = {
|
||||
{
|
||||
name: 'order',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
defaultValue: undefined,
|
||||
admin: {
|
||||
position: 'sidebar'
|
||||
}
|
||||
|
||||
8
src/collections/Settings/index.ts
Normal file
8
src/collections/Settings/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { CollectionConfig } from 'payload';
|
||||
|
||||
export const Settings: CollectionConfig = {
|
||||
slug: 'settings',
|
||||
fields: [
|
||||
|
||||
]
|
||||
}
|
||||
@@ -90,8 +90,12 @@ export interface Config {
|
||||
db: {
|
||||
defaultIDType: number;
|
||||
};
|
||||
globals: {};
|
||||
globalsSelect: {};
|
||||
globals: {
|
||||
nav: Nav;
|
||||
};
|
||||
globalsSelect: {
|
||||
nav: NavSelect<false> | NavSelect<true>;
|
||||
};
|
||||
locale: null;
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
@@ -141,6 +145,14 @@ export interface Page {
|
||||
};
|
||||
[k: string]: unknown;
|
||||
} | null;
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
/**
|
||||
* Maximum upload file size: 12MB. Recommended file size for images is <500KB.
|
||||
*/
|
||||
image?: (number | null) | Media;
|
||||
description?: string | null;
|
||||
};
|
||||
/**
|
||||
* When enabled, the slug will auto-generate from the title field on save and autosave.
|
||||
*/
|
||||
@@ -149,6 +161,25 @@ export interface Page {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "media".
|
||||
*/
|
||||
export interface Media {
|
||||
id: number;
|
||||
alt: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
thumbnailURL?: string | null;
|
||||
filename?: string | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
focalX?: number | null;
|
||||
focalY?: number | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "projects".
|
||||
@@ -226,25 +257,6 @@ export interface User {
|
||||
| null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "media".
|
||||
*/
|
||||
export interface Media {
|
||||
id: number;
|
||||
alt: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
thumbnailURL?: string | null;
|
||||
filename?: string | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
focalX?: number | null;
|
||||
focalY?: number | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
@@ -321,6 +333,13 @@ export interface PayloadMigration {
|
||||
export interface PagesSelect<T extends boolean = true> {
|
||||
title?: T;
|
||||
richText?: T;
|
||||
meta?:
|
||||
| T
|
||||
| {
|
||||
title?: T;
|
||||
image?: T;
|
||||
description?: T;
|
||||
};
|
||||
generateSlug?: T;
|
||||
slug?: T;
|
||||
updatedAt?: T;
|
||||
@@ -429,6 +448,34 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "nav".
|
||||
*/
|
||||
export interface Nav {
|
||||
id: number;
|
||||
items: {
|
||||
page: number | Page;
|
||||
id?: string | null;
|
||||
}[];
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "nav_select".
|
||||
*/
|
||||
export interface NavSelect<T extends boolean = true> {
|
||||
items?:
|
||||
| T
|
||||
| {
|
||||
page?: T;
|
||||
id?: T;
|
||||
};
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
globalType?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
|
||||
@@ -12,6 +12,10 @@ import { Media } from './collections/Media'
|
||||
import { Page } from './collections/Page'
|
||||
import { Projects } from './collections/Projects'
|
||||
import { Categories } from './collections/Categories'
|
||||
import { Nav } from './collections/Nav'
|
||||
import { seoPlugin } from '@payloadcms/plugin-seo'
|
||||
import { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
|
||||
import { plugins } from './plugins'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
@@ -23,7 +27,16 @@ export default buildConfig({
|
||||
baseDir: path.resolve(dirname),
|
||||
},
|
||||
},
|
||||
collections: [Page, Projects, Categories, Users, Media],
|
||||
collections: [
|
||||
Page,
|
||||
Projects,
|
||||
Categories,
|
||||
Users,
|
||||
Media,
|
||||
],
|
||||
globals: [
|
||||
Nav,
|
||||
],
|
||||
editor: lexicalEditor({
|
||||
features: ({ defaultFeatures, rootFeatures }) => [
|
||||
...defaultFeatures,
|
||||
@@ -62,7 +75,7 @@ export default buildConfig({
|
||||
}),
|
||||
sharp,
|
||||
plugins: [
|
||||
payloadCloudPlugin(),
|
||||
...plugins
|
||||
// storage-adapter-placeholder
|
||||
],
|
||||
})
|
||||
|
||||
24
src/plugins/index.ts
Normal file
24
src/plugins/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { payloadCloudPlugin } from "@payloadcms/payload-cloud";
|
||||
import { seoPlugin } from "@payloadcms/plugin-seo";
|
||||
import { GenerateTitle, GenerateURL } from "@payloadcms/plugin-seo/types";
|
||||
import { Plugin } from "payload";
|
||||
import { Page, Project } from "../payload-types";
|
||||
import { getServerSideURL } from "@/utilities/getURL";
|
||||
|
||||
const generateTitle: GenerateTitle<Project | Page> = ({ doc }) => {
|
||||
return doc?.title ? `${doc.title} | Payload Website Template` : 'Payload Website Template'
|
||||
}
|
||||
|
||||
const generateURL: GenerateURL<Project | Page> = ({ doc }) => {
|
||||
const url = getServerSideURL()
|
||||
|
||||
return doc?.slug ? `${url}/${doc.slug}` : url
|
||||
}
|
||||
|
||||
export const plugins: Plugin[] = [
|
||||
payloadCloudPlugin(),
|
||||
seoPlugin({
|
||||
generateTitle,
|
||||
generateURL,
|
||||
}),
|
||||
]
|
||||
Reference in New Issue
Block a user