kofi-stack-template-generator 2.1.27 → 2.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/index.js +336 -9
  2. package/package.json +8 -8
  3. package/src/templates.generated.ts +70 -11
  4. package/templates/marketing/payload/src/Footer/config.ts.hbs +178 -0
  5. package/templates/marketing/payload/src/Footer/hooks/revalidateFooter.ts.hbs +13 -0
  6. package/templates/marketing/payload/src/Footer/index.ts.hbs +1 -0
  7. package/templates/marketing/payload/src/Header/RowLabel.tsx.hbs +21 -0
  8. package/templates/marketing/payload/src/Header/config.ts.hbs +208 -0
  9. package/templates/marketing/payload/src/Header/hooks/revalidateHeader.ts.hbs +13 -0
  10. package/templates/marketing/payload/src/Header/index.ts.hbs +1 -0
  11. package/templates/marketing/payload/src/access/anyone.ts.hbs +3 -0
  12. package/templates/marketing/payload/src/access/authenticated.ts.hbs +9 -0
  13. package/templates/marketing/payload/src/access/authenticatedOrPublished.ts.hbs +13 -0
  14. package/templates/marketing/payload/src/access/index.ts.hbs +3 -0
  15. package/templates/marketing/payload/src/app/(frontend)/next/seed/route.ts.hbs +31 -0
  16. package/templates/marketing/payload/src/collections/Categories/index.ts.hbs +28 -0
  17. package/templates/marketing/payload/src/collections/FAQs/index.ts.hbs +100 -0
  18. package/templates/marketing/payload/src/collections/Media.ts.hbs +148 -28
  19. package/templates/marketing/payload/src/collections/Pages/hooks/revalidatePage.ts.hbs +43 -0
  20. package/templates/marketing/payload/src/collections/Pages/index.ts.hbs +142 -0
  21. package/templates/marketing/payload/src/collections/Posts/hooks/populateAuthors.ts.hbs +41 -0
  22. package/templates/marketing/payload/src/collections/Posts/hooks/revalidatePost.ts.hbs +44 -0
  23. package/templates/marketing/payload/src/collections/Posts/index.ts.hbs +244 -0
  24. package/templates/marketing/payload/src/collections/Users/index.ts.hbs +26 -0
  25. package/templates/marketing/payload/src/collections/index.ts.hbs +6 -4
  26. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.scss.hbs +12 -0
  27. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.tsx.hbs +89 -0
  28. package/templates/marketing/payload/src/components/BeforeDashboard/index.scss.hbs +24 -0
  29. package/templates/marketing/payload/src/components/BeforeDashboard/index.tsx.hbs +69 -0
  30. package/templates/marketing/payload/src/components/BeforeLogin/index.tsx.hbs +14 -0
  31. package/templates/marketing/payload/src/components/Link/index.tsx.hbs +79 -0
  32. package/templates/marketing/payload/src/components/Media/index.tsx.hbs +67 -0
  33. package/templates/marketing/payload/src/components/RichText/index.tsx.hbs +44 -0
  34. package/templates/marketing/payload/src/endpoints/seed/home.ts.hbs +76 -0
  35. package/templates/marketing/payload/src/endpoints/seed/image-1.ts.hbs +5 -0
  36. package/templates/marketing/payload/src/endpoints/seed/image-2.ts.hbs +5 -0
  37. package/templates/marketing/payload/src/endpoints/seed/image-hero.ts.hbs +5 -0
  38. package/templates/marketing/payload/src/endpoints/seed/index.ts.hbs +235 -0
  39. package/templates/marketing/payload/src/endpoints/seed/post-1.ts.hbs +252 -0
  40. package/templates/marketing/payload/src/fields/defaultLexical.ts.hbs +73 -0
  41. package/templates/marketing/payload/src/fields/index.ts.hbs +3 -0
  42. package/templates/marketing/payload/src/fields/link.ts.hbs +139 -0
  43. package/templates/marketing/payload/src/fields/linkGroup.ts.hbs +28 -0
  44. package/templates/marketing/payload/src/globals/index.ts.hbs +2 -2
  45. package/templates/marketing/payload/src/heros/HighImpact/index.tsx.hbs +53 -0
  46. package/templates/marketing/payload/src/heros/LowImpact/index.tsx.hbs +48 -0
  47. package/templates/marketing/payload/src/heros/MediumImpact/index.tsx.hbs +46 -0
  48. package/templates/marketing/payload/src/heros/PostHero/index.tsx.hbs +68 -0
  49. package/templates/marketing/payload/src/heros/ProductShowcase/index.tsx.hbs +88 -0
  50. package/templates/marketing/payload/src/heros/RenderHero.tsx.hbs +27 -0
  51. package/templates/marketing/payload/src/heros/config.ts.hbs +112 -0
  52. package/templates/marketing/payload/src/heros/index.ts.hbs +7 -0
  53. package/templates/marketing/payload/src/hooks/index.ts.hbs +2 -0
  54. package/templates/marketing/payload/src/hooks/populatePublishedAt.ts.hbs +15 -0
  55. package/templates/marketing/payload/src/hooks/revalidateRedirects.ts.hbs +11 -0
  56. package/templates/marketing/payload/src/payload.config.ts.hbs +32 -8
  57. package/templates/marketing/payload/src/providers/HeaderTheme/index.tsx.hbs +34 -0
  58. package/templates/marketing/payload/src/providers/Theme/InitTheme/index.tsx.hbs +44 -0
  59. package/templates/marketing/payload/src/providers/Theme/index.tsx.hbs +60 -0
  60. package/templates/marketing/payload/src/providers/Theme/shared.ts.hbs +17 -0
  61. package/templates/marketing/payload/src/providers/Theme/types.ts.hbs +10 -0
  62. package/templates/marketing/payload/src/providers/index.tsx.hbs +18 -0
  63. package/templates/marketing/payload/src/utilities/canUseDOM.ts.hbs +1 -0
  64. package/templates/marketing/payload/src/utilities/deepMerge.ts.hbs +35 -0
  65. package/templates/marketing/payload/src/utilities/formatAuthors.ts.hbs +24 -0
  66. package/templates/marketing/payload/src/utilities/formatDateTime.ts.hbs +13 -0
  67. package/templates/marketing/payload/src/utilities/generateMeta.ts.hbs +87 -0
  68. package/templates/marketing/payload/src/utilities/generatePreviewPath.ts.hbs +33 -0
  69. package/templates/marketing/payload/src/utilities/getURL.ts.hbs +26 -0
  70. package/templates/marketing/payload/src/utilities/index.ts.hbs +8 -0
  71. package/templates/marketing/payload/src/utilities/mergeOpenGraph.ts.hbs +26 -0
  72. package/templates/marketing/payload/src/collections/Pages.ts.hbs +0 -66
  73. package/templates/marketing/payload/src/collections/Posts.ts.hbs +0 -65
  74. package/templates/marketing/payload/src/collections/Users.ts.hbs +0 -25
  75. package/templates/marketing/payload/src/globals/Navigation.ts.hbs +0 -51
  76. package/templates/marketing/payload/src/globals/SiteSettings.ts.hbs +0 -49
@@ -0,0 +1,60 @@
1
+ "use client"
2
+
3
+ import type React from "react"
4
+ import { createContext, use, useCallback, useEffect, useState } from "react"
5
+
6
+ import type { Theme, ThemeContextType } from "./types"
7
+
8
+ import canUseDOM from "@/utilities/canUseDOM"
9
+ import { defaultTheme, getImplicitPreference, themeLocalStorageKey } from "./shared"
10
+ import { themeIsValid } from "./types"
11
+
12
+ const initialContext: ThemeContextType = {
13
+ setTheme: () => null,
14
+ theme: undefined,
15
+ }
16
+
17
+ const ThemeContext = createContext(initialContext)
18
+
19
+ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
20
+ const [theme, setThemeState] = useState<Theme | undefined>(
21
+ canUseDOM ? (document.documentElement.getAttribute("data-theme") as Theme) : undefined,
22
+ )
23
+
24
+ const setTheme = useCallback((themeToSet: Theme | null) => {
25
+ if (themeToSet === null) {
26
+ // 'auto' mode - use system preference
27
+ const implicitPreference = getImplicitPreference()
28
+ const resolvedTheme = implicitPreference || defaultTheme
29
+ document.documentElement.setAttribute("data-theme", resolvedTheme)
30
+ setThemeState(resolvedTheme)
31
+ } else {
32
+ setThemeState(themeToSet)
33
+ document.documentElement.setAttribute("data-theme", themeToSet)
34
+ }
35
+ }, [])
36
+
37
+ useEffect(() => {
38
+ let themeToSet: Theme = defaultTheme
39
+ const preference = window.localStorage.getItem(themeLocalStorageKey)
40
+
41
+ if (themeIsValid(preference)) {
42
+ // User explicitly chose light or dark
43
+ themeToSet = preference
44
+ } else if (preference === "auto") {
45
+ // User explicitly chose system preference
46
+ const implicitPreference = getImplicitPreference()
47
+ if (implicitPreference) {
48
+ themeToSet = implicitPreference
49
+ }
50
+ }
51
+ // If no preference, use defaultTheme (light)
52
+
53
+ document.documentElement.setAttribute("data-theme", themeToSet)
54
+ setThemeState(themeToSet)
55
+ }, [])
56
+
57
+ return <ThemeContext value=\{{ setTheme, theme }}>{children}</ThemeContext>
58
+ }
59
+
60
+ export const useTheme = (): ThemeContextType => use(ThemeContext)
@@ -0,0 +1,17 @@
1
+ import type { Theme } from "./types"
2
+
3
+ export const themeLocalStorageKey = "payload-theme"
4
+
5
+ export const defaultTheme = "light"
6
+
7
+ export const getImplicitPreference = (): Theme | null => {
8
+ const mediaQuery = "(prefers-color-scheme: dark)"
9
+ const mql = window.matchMedia(mediaQuery)
10
+ const hasImplicitPreference = typeof mql.matches === "boolean"
11
+
12
+ if (hasImplicitPreference) {
13
+ return mql.matches ? "dark" : "light"
14
+ }
15
+
16
+ return null
17
+ }
@@ -0,0 +1,10 @@
1
+ export type Theme = "dark" | "light"
2
+
3
+ export interface ThemeContextType {
4
+ setTheme: (theme: Theme | null) => void
5
+ theme?: Theme | null
6
+ }
7
+
8
+ export function themeIsValid(string: null | string): string is Theme {
9
+ return string ? ["dark", "light"].includes(string) : false
10
+ }
@@ -0,0 +1,18 @@
1
+ "use client"
2
+
3
+ import type React from "react"
4
+
5
+ import { HeaderThemeProvider } from "./HeaderTheme"
6
+ import { ThemeProvider } from "./Theme"
7
+
8
+ export const Providers: React.FC<{
9
+ children: React.ReactNode
10
+ }> = ({ children }) => {
11
+ return (
12
+ <ThemeProvider>
13
+ <HeaderThemeProvider>
14
+ {children}
15
+ </HeaderThemeProvider>
16
+ </ThemeProvider>
17
+ )
18
+ }
@@ -0,0 +1 @@
1
+ export default !!(typeof window !== "undefined" && window.document && window.document.createElement)
@@ -0,0 +1,35 @@
1
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
+ // @ts-nocheck
3
+
4
+ /**
5
+ * Simple object check.
6
+ * @param item
7
+ * @returns {boolean}
8
+ */
9
+ export function isObject(item: unknown): item is object {
10
+ return typeof item === "object" && !Array.isArray(item)
11
+ }
12
+
13
+ /**
14
+ * Deep merge two objects.
15
+ * @param target
16
+ * @param ...sources
17
+ */
18
+ export default function deepMerge<T, R>(target: T, source: R): T {
19
+ const output = { ...target }
20
+ if (isObject(target) && isObject(source)) {
21
+ Object.keys(source).forEach((key) => {
22
+ if (isObject(source[key])) {
23
+ if (!(key in target)) {
24
+ Object.assign(output, { [key]: source[key] })
25
+ } else {
26
+ output[key] = deepMerge(target[key], source[key])
27
+ }
28
+ } else {
29
+ Object.assign(output, { [key]: source[key] })
30
+ }
31
+ })
32
+ }
33
+
34
+ return output
35
+ }
@@ -0,0 +1,24 @@
1
+ import type { Post } from "@/payload-types"
2
+
3
+ /**
4
+ * Formats an array of populatedAuthors from Posts into a prettified string.
5
+ * @param authors - The populatedAuthors array from a Post.
6
+ * @returns A prettified string of authors.
7
+ * @example
8
+ *
9
+ * [Author1, Author2] becomes 'Author1 and Author2'
10
+ * [Author1, Author2, Author3] becomes 'Author1, Author2, and Author3'
11
+ *
12
+ */
13
+ export const formatAuthors = (
14
+ authors: NonNullable<NonNullable<Post["populatedAuthors"]>[number]>[],
15
+ ) => {
16
+ // Ensure we don't have any authors without a name
17
+ const authorNames = authors.map((author) => author.name).filter(Boolean)
18
+
19
+ if (authorNames.length === 0) return ""
20
+ if (authorNames.length === 1) return authorNames[0]
21
+ if (authorNames.length === 2) return `${authorNames[0]} and ${authorNames[1]}`
22
+
23
+ return `${authorNames.slice(0, -1).join(", ")} and ${authorNames[authorNames.length - 1]}`
24
+ }
@@ -0,0 +1,13 @@
1
+ export const formatDateTime = (timestamp: string): string => {
2
+ const now = new Date()
3
+ let date = now
4
+ if (timestamp) date = new Date(timestamp)
5
+ const months = date.getMonth()
6
+ const days = date.getDate()
7
+
8
+ const MM = months + 1 < 10 ? `0${months + 1}` : months + 1
9
+ const DD = days < 10 ? `0${days}` : days
10
+ const YYYY = date.getFullYear()
11
+
12
+ return `${MM}/${DD}/${YYYY}`
13
+ }
@@ -0,0 +1,87 @@
1
+ import type { Metadata } from "next"
2
+
3
+ import type { Config, Media, Page, Post } from "../payload-types"
4
+
5
+ import { getServerSideURL } from "./getURL"
6
+ import { mergeOpenGraph } from "./mergeOpenGraph"
7
+
8
+ const getImageURL = (image?: Media | Config["db"]["defaultIDType"] | null) => {
9
+ const serverUrl = getServerSideURL()
10
+
11
+ let url = `${serverUrl}/og-image.png`
12
+
13
+ if (image && typeof image === "object" && "url" in image) {
14
+ const ogUrl = image.sizes?.og?.url
15
+
16
+ url = ogUrl ? `${serverUrl}${ogUrl}` : `${serverUrl}${image.url}`
17
+ }
18
+
19
+ return url
20
+ }
21
+
22
+ // Default keywords for SEO
23
+ const defaultKeywords = [
24
+ "{{projectName}}",
25
+ "website",
26
+ "Next.js",
27
+ "Payload CMS",
28
+ ]
29
+
30
+ export const generateMeta = async (args: {
31
+ doc: Partial<Page> | Partial<Post> | null
32
+ }): Promise<Metadata> => {
33
+ const { doc } = args
34
+ const serverUrl = getServerSideURL()
35
+
36
+ const ogImage = getImageURL(doc?.meta?.image)
37
+
38
+ const title = doc?.meta?.title
39
+ ? `${doc?.meta?.title} | {{projectName}}`
40
+ : "{{projectName}}"
41
+
42
+ const description =
43
+ doc?.meta?.description ||
44
+ "Welcome to {{projectName}}. Built with Payload CMS and Next.js."
45
+
46
+ // Generate canonical URL
47
+ const slug = Array.isArray(doc?.slug) ? doc?.slug.join("/") : doc?.slug || ""
48
+ const canonicalUrl = slug === "home" ? serverUrl : `${serverUrl}/${slug}`
49
+
50
+ return {
51
+ title,
52
+ description,
53
+ keywords: defaultKeywords,
54
+ authors: [{ name: "{{projectName}}", url: serverUrl }],
55
+ creator: "{{projectName}}",
56
+ publisher: "{{projectName}}",
57
+ robots: {
58
+ index: true,
59
+ follow: true,
60
+ googleBot: {
61
+ index: true,
62
+ follow: true,
63
+ "max-video-preview": -1,
64
+ "max-image-preview": "large",
65
+ "max-snippet": -1,
66
+ },
67
+ },
68
+ alternates: {
69
+ canonical: canonicalUrl,
70
+ },
71
+ openGraph: mergeOpenGraph({
72
+ description,
73
+ images: ogImage
74
+ ? [
75
+ {
76
+ url: ogImage,
77
+ width: 1200,
78
+ height: 630,
79
+ alt: title,
80
+ },
81
+ ]
82
+ : undefined,
83
+ title,
84
+ url: canonicalUrl,
85
+ }),
86
+ }
87
+ }
@@ -0,0 +1,33 @@
1
+ import type { CollectionSlug, PayloadRequest } from "payload"
2
+
3
+ const collectionPrefixMap: Partial<Record<CollectionSlug, string>> = {
4
+ posts: "/posts",
5
+ pages: "",
6
+ }
7
+
8
+ type Props = {
9
+ collection: keyof typeof collectionPrefixMap
10
+ slug: string
11
+ req: PayloadRequest
12
+ }
13
+
14
+ export const generatePreviewPath = ({ collection, slug }: Props) => {
15
+ // Allow empty strings, e.g. for the homepage
16
+ if (slug === undefined || slug === null) {
17
+ return null
18
+ }
19
+
20
+ // Encode to support slugs with special characters
21
+ const encodedSlug = encodeURIComponent(slug)
22
+
23
+ const encodedParams = new URLSearchParams({
24
+ slug: encodedSlug,
25
+ collection,
26
+ path: `${collectionPrefixMap[collection]}/${encodedSlug}`,
27
+ previewSecret: process.env.PREVIEW_SECRET || "",
28
+ })
29
+
30
+ const url = `/next/preview?${encodedParams.toString()}`
31
+
32
+ return url
33
+ }
@@ -0,0 +1,26 @@
1
+ import canUseDOM from "./canUseDOM"
2
+
3
+ export const getServerSideURL = () => {
4
+ return (
5
+ process.env.NEXT_PUBLIC_SERVER_URL ||
6
+ (process.env.VERCEL_PROJECT_PRODUCTION_URL
7
+ ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
8
+ : "http://localhost:3000")
9
+ )
10
+ }
11
+
12
+ export const getClientSideURL = () => {
13
+ if (canUseDOM) {
14
+ const protocol = window.location.protocol
15
+ const domain = window.location.hostname
16
+ const port = window.location.port
17
+
18
+ return `${protocol}//${domain}${port ? `:${port}` : ""}`
19
+ }
20
+
21
+ if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {
22
+ return `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
23
+ }
24
+
25
+ return process.env.NEXT_PUBLIC_SERVER_URL || ""
26
+ }
@@ -0,0 +1,8 @@
1
+ export { default as deepMerge, isObject } from "./deepMerge"
2
+ export { default as canUseDOM } from "./canUseDOM"
3
+ export { getServerSideURL, getClientSideURL } from "./getURL"
4
+ export { generatePreviewPath } from "./generatePreviewPath"
5
+ export { mergeOpenGraph } from "./mergeOpenGraph"
6
+ export { generateMeta } from "./generateMeta"
7
+ export { formatAuthors } from "./formatAuthors"
8
+ export { formatDateTime } from "./formatDateTime"
@@ -0,0 +1,26 @@
1
+ import type { Metadata } from "next"
2
+ import { getServerSideURL } from "./getURL"
3
+
4
+ const defaultOpenGraph: Metadata["openGraph"] = {
5
+ type: "website",
6
+ description:
7
+ "Welcome to {{projectName}}. Built with Payload CMS and Next.js.",
8
+ images: [
9
+ {
10
+ url: `${getServerSideURL()}/og-image.png`,
11
+ width: 1200,
12
+ height: 630,
13
+ alt: "{{projectName}}",
14
+ },
15
+ ],
16
+ siteName: "{{projectName}}",
17
+ title: "{{projectName}}",
18
+ }
19
+
20
+ export const mergeOpenGraph = (og?: Metadata["openGraph"]): Metadata["openGraph"] => {
21
+ return {
22
+ ...defaultOpenGraph,
23
+ ...og,
24
+ images: og?.images ? og.images : defaultOpenGraph.images,
25
+ }
26
+ }
@@ -1,66 +0,0 @@
1
- import type { CollectionConfig } from 'payload'
2
- import {
3
- HeroBlock,
4
- LogoBannerBlock,
5
- FeaturesBlock,
6
- BenefitsBlock,
7
- PricingBlock,
8
- TestimonialsBlock,
9
- FAQBlock,
10
- ContentBlock,
11
- CTABlock,
12
- } from '../blocks'
13
-
14
- export const Pages: CollectionConfig = {
15
- slug: 'pages',
16
- admin: {
17
- useAsTitle: 'title',
18
- defaultColumns: ['title', 'slug', 'status', 'updatedAt'],
19
- },
20
- access: {
21
- read: () => true,
22
- },
23
- fields: [
24
- {
25
- name: 'title',
26
- type: 'text',
27
- required: true,
28
- },
29
- {
30
- name: 'slug',
31
- type: 'text',
32
- required: true,
33
- unique: true,
34
- admin: {
35
- position: 'sidebar',
36
- },
37
- },
38
- {
39
- name: 'status',
40
- type: 'select',
41
- options: [
42
- { label: 'Draft', value: 'draft' },
43
- { label: 'Published', value: 'published' },
44
- ],
45
- defaultValue: 'draft',
46
- admin: {
47
- position: 'sidebar',
48
- },
49
- },
50
- {
51
- name: 'layout',
52
- type: 'blocks',
53
- blocks: [
54
- HeroBlock,
55
- LogoBannerBlock,
56
- FeaturesBlock,
57
- BenefitsBlock,
58
- PricingBlock,
59
- TestimonialsBlock,
60
- FAQBlock,
61
- ContentBlock,
62
- CTABlock,
63
- ],
64
- },
65
- ],
66
- }
@@ -1,65 +0,0 @@
1
- import type { CollectionConfig } from 'payload'
2
-
3
- export const Posts: CollectionConfig = {
4
- slug: 'posts',
5
- admin: {
6
- useAsTitle: 'title',
7
- defaultColumns: ['title', 'author', 'status', 'publishedAt'],
8
- },
9
- access: {
10
- read: () => true,
11
- },
12
- fields: [
13
- {
14
- name: 'title',
15
- type: 'text',
16
- required: true,
17
- },
18
- {
19
- name: 'slug',
20
- type: 'text',
21
- required: true,
22
- unique: true,
23
- },
24
- {
25
- name: 'excerpt',
26
- type: 'textarea',
27
- },
28
- {
29
- name: 'content',
30
- type: 'richText',
31
- },
32
- {
33
- name: 'featuredImage',
34
- type: 'upload',
35
- relationTo: 'media',
36
- },
37
- {
38
- name: 'author',
39
- type: 'relationship',
40
- relationTo: 'users',
41
- admin: {
42
- position: 'sidebar',
43
- },
44
- },
45
- {
46
- name: 'status',
47
- type: 'select',
48
- options: [
49
- { label: 'Draft', value: 'draft' },
50
- { label: 'Published', value: 'published' },
51
- ],
52
- defaultValue: 'draft',
53
- admin: {
54
- position: 'sidebar',
55
- },
56
- },
57
- {
58
- name: 'publishedAt',
59
- type: 'date',
60
- admin: {
61
- position: 'sidebar',
62
- },
63
- },
64
- ],
65
- }
@@ -1,25 +0,0 @@
1
- import type { CollectionConfig } from 'payload'
2
-
3
- export const Users: CollectionConfig = {
4
- slug: 'users',
5
- admin: {
6
- useAsTitle: 'email',
7
- },
8
- auth: true,
9
- fields: [
10
- {
11
- name: 'name',
12
- type: 'text',
13
- },
14
- {
15
- name: 'role',
16
- type: 'select',
17
- options: [
18
- { label: 'Admin', value: 'admin' },
19
- { label: 'Editor', value: 'editor' },
20
- ],
21
- defaultValue: 'editor',
22
- required: true,
23
- },
24
- ],
25
- }
@@ -1,51 +0,0 @@
1
- import type { GlobalConfig } from 'payload'
2
-
3
- export const Navigation: GlobalConfig = {
4
- slug: 'navigation',
5
- access: {
6
- read: () => true,
7
- },
8
- fields: [
9
- {
10
- name: 'items',
11
- type: 'array',
12
- fields: [
13
- {
14
- name: 'label',
15
- type: 'text',
16
- required: true,
17
- },
18
- {
19
- name: 'link',
20
- type: 'group',
21
- fields: [
22
- {
23
- name: 'type',
24
- type: 'radio',
25
- options: [
26
- { label: 'Internal', value: 'internal' },
27
- { label: 'External', value: 'external' },
28
- ],
29
- defaultValue: 'internal',
30
- },
31
- {
32
- name: 'page',
33
- type: 'relationship',
34
- relationTo: 'pages',
35
- admin: {
36
- condition: (_, siblingData) => siblingData?.type === 'internal',
37
- },
38
- },
39
- {
40
- name: 'url',
41
- type: 'text',
42
- admin: {
43
- condition: (_, siblingData) => siblingData?.type === 'external',
44
- },
45
- },
46
- ],
47
- },
48
- ],
49
- },
50
- ],
51
- }
@@ -1,49 +0,0 @@
1
- import type { GlobalConfig } from 'payload'
2
-
3
- export const SiteSettings: GlobalConfig = {
4
- slug: 'site-settings',
5
- access: {
6
- read: () => true,
7
- },
8
- fields: [
9
- {
10
- name: 'siteName',
11
- type: 'text',
12
- required: true,
13
- },
14
- {
15
- name: 'siteDescription',
16
- type: 'textarea',
17
- },
18
- {
19
- name: 'logo',
20
- type: 'upload',
21
- relationTo: 'media',
22
- },
23
- {
24
- name: 'favicon',
25
- type: 'upload',
26
- relationTo: 'media',
27
- },
28
- {
29
- name: 'socialLinks',
30
- type: 'array',
31
- fields: [
32
- {
33
- name: 'platform',
34
- type: 'select',
35
- options: [
36
- { label: 'Twitter', value: 'twitter' },
37
- { label: 'GitHub', value: 'github' },
38
- { label: 'LinkedIn', value: 'linkedin' },
39
- { label: 'Discord', value: 'discord' },
40
- ],
41
- },
42
- {
43
- name: 'url',
44
- type: 'text',
45
- },
46
- ],
47
- },
48
- ],
49
- }