kofi-stack-template-generator 2.1.26 → 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 (83) hide show
  1. package/dist/index.js +343 -16
  2. package/package.json +8 -8
  3. package/src/templates.generated.ts +77 -18
  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/app/(payload)/admin/[[...segments]]/not-found.tsx.hbs +13 -6
  17. package/templates/marketing/payload/src/app/(payload)/admin/[[...segments]]/page.tsx.hbs +13 -6
  18. package/templates/marketing/payload/src/app/(payload)/api/[...slug]/route.ts.hbs +17 -7
  19. package/templates/marketing/payload/src/app/(payload)/api/graphql/route.ts.hbs +7 -4
  20. package/templates/marketing/payload/src/app/(payload)/api/graphql-playground/route.ts.hbs +5 -3
  21. package/templates/marketing/payload/src/app/(payload)/layout.tsx.hbs +20 -13
  22. package/templates/marketing/payload/src/collections/Categories/index.ts.hbs +28 -0
  23. package/templates/marketing/payload/src/collections/FAQs/index.ts.hbs +100 -0
  24. package/templates/marketing/payload/src/collections/Media.ts.hbs +148 -28
  25. package/templates/marketing/payload/src/collections/Pages/hooks/revalidatePage.ts.hbs +43 -0
  26. package/templates/marketing/payload/src/collections/Pages/index.ts.hbs +142 -0
  27. package/templates/marketing/payload/src/collections/Posts/hooks/populateAuthors.ts.hbs +41 -0
  28. package/templates/marketing/payload/src/collections/Posts/hooks/revalidatePost.ts.hbs +44 -0
  29. package/templates/marketing/payload/src/collections/Posts/index.ts.hbs +244 -0
  30. package/templates/marketing/payload/src/collections/Users/index.ts.hbs +26 -0
  31. package/templates/marketing/payload/src/collections/index.ts.hbs +6 -4
  32. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.scss.hbs +12 -0
  33. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.tsx.hbs +89 -0
  34. package/templates/marketing/payload/src/components/BeforeDashboard/index.scss.hbs +24 -0
  35. package/templates/marketing/payload/src/components/BeforeDashboard/index.tsx.hbs +69 -0
  36. package/templates/marketing/payload/src/components/BeforeLogin/index.tsx.hbs +14 -0
  37. package/templates/marketing/payload/src/components/Link/index.tsx.hbs +79 -0
  38. package/templates/marketing/payload/src/components/Media/index.tsx.hbs +67 -0
  39. package/templates/marketing/payload/src/components/RichText/index.tsx.hbs +44 -0
  40. package/templates/marketing/payload/src/endpoints/seed/home.ts.hbs +76 -0
  41. package/templates/marketing/payload/src/endpoints/seed/image-1.ts.hbs +5 -0
  42. package/templates/marketing/payload/src/endpoints/seed/image-2.ts.hbs +5 -0
  43. package/templates/marketing/payload/src/endpoints/seed/image-hero.ts.hbs +5 -0
  44. package/templates/marketing/payload/src/endpoints/seed/index.ts.hbs +235 -0
  45. package/templates/marketing/payload/src/endpoints/seed/post-1.ts.hbs +252 -0
  46. package/templates/marketing/payload/src/fields/defaultLexical.ts.hbs +73 -0
  47. package/templates/marketing/payload/src/fields/index.ts.hbs +3 -0
  48. package/templates/marketing/payload/src/fields/link.ts.hbs +139 -0
  49. package/templates/marketing/payload/src/fields/linkGroup.ts.hbs +28 -0
  50. package/templates/marketing/payload/src/globals/index.ts.hbs +2 -2
  51. package/templates/marketing/payload/src/heros/HighImpact/index.tsx.hbs +53 -0
  52. package/templates/marketing/payload/src/heros/LowImpact/index.tsx.hbs +48 -0
  53. package/templates/marketing/payload/src/heros/MediumImpact/index.tsx.hbs +46 -0
  54. package/templates/marketing/payload/src/heros/PostHero/index.tsx.hbs +68 -0
  55. package/templates/marketing/payload/src/heros/ProductShowcase/index.tsx.hbs +88 -0
  56. package/templates/marketing/payload/src/heros/RenderHero.tsx.hbs +27 -0
  57. package/templates/marketing/payload/src/heros/config.ts.hbs +112 -0
  58. package/templates/marketing/payload/src/heros/index.ts.hbs +7 -0
  59. package/templates/marketing/payload/src/hooks/index.ts.hbs +2 -0
  60. package/templates/marketing/payload/src/hooks/populatePublishedAt.ts.hbs +15 -0
  61. package/templates/marketing/payload/src/hooks/revalidateRedirects.ts.hbs +11 -0
  62. package/templates/marketing/payload/src/payload.config.ts.hbs +32 -8
  63. package/templates/marketing/payload/src/providers/HeaderTheme/index.tsx.hbs +34 -0
  64. package/templates/marketing/payload/src/providers/Theme/InitTheme/index.tsx.hbs +44 -0
  65. package/templates/marketing/payload/src/providers/Theme/index.tsx.hbs +60 -0
  66. package/templates/marketing/payload/src/providers/Theme/shared.ts.hbs +17 -0
  67. package/templates/marketing/payload/src/providers/Theme/types.ts.hbs +10 -0
  68. package/templates/marketing/payload/src/providers/index.tsx.hbs +18 -0
  69. package/templates/marketing/payload/src/utilities/canUseDOM.ts.hbs +1 -0
  70. package/templates/marketing/payload/src/utilities/deepMerge.ts.hbs +35 -0
  71. package/templates/marketing/payload/src/utilities/formatAuthors.ts.hbs +24 -0
  72. package/templates/marketing/payload/src/utilities/formatDateTime.ts.hbs +13 -0
  73. package/templates/marketing/payload/src/utilities/generateMeta.ts.hbs +87 -0
  74. package/templates/marketing/payload/src/utilities/generatePreviewPath.ts.hbs +33 -0
  75. package/templates/marketing/payload/src/utilities/getURL.ts.hbs +26 -0
  76. package/templates/marketing/payload/src/utilities/index.ts.hbs +8 -0
  77. package/templates/marketing/payload/src/utilities/mergeOpenGraph.ts.hbs +26 -0
  78. package/templates/marketing/payload/tsconfig.json.hbs +1 -0
  79. package/templates/marketing/payload/src/collections/Pages.ts.hbs +0 -66
  80. package/templates/marketing/payload/src/collections/Posts.ts.hbs +0 -65
  81. package/templates/marketing/payload/src/collections/Users.ts.hbs +0 -25
  82. package/templates/marketing/payload/src/globals/Navigation.ts.hbs +0 -51
  83. package/templates/marketing/payload/src/globals/SiteSettings.ts.hbs +0 -49
package/dist/index.js CHANGED
@@ -579,6 +579,17 @@ GCS_CREDENTIALS="{}" # JSON service account key
579
579
  }
580
580
  `,
581
581
  "marketing/payload/postcss.config.mjs.hbs": "export default {\n plugins: {\n '@tailwindcss/postcss': {},\n },\n}\n",
582
+ "marketing/payload/src/Footer/config.ts.hbs": 'import type { GlobalConfig } from "payload"\n\nimport { link } from "@/fields/link"\nimport { revalidateFooter } from "./hooks/revalidateFooter"\n\nexport const Footer: GlobalConfig = {\n slug: "footer",\n access: {\n read: () => true,\n },\n fields: [\n // Link Columns - organized groups of links\n {\n name: "columns",\n type: "array",\n label: "Link Columns",\n maxRows: 5,\n admin: {\n initCollapsed: true,\n description: "Add columns of links (e.g., Solutions, Resources, Company)",\n },\n fields: [\n {\n name: "title",\n type: "text",\n required: true,\n label: "Column Title",\n },\n {\n name: "links",\n type: "array",\n label: "Links",\n maxRows: 10,\n fields: [\n link({\n appearances: false,\n }),\n ],\n admin: {\n initCollapsed: true,\n },\n },\n ],\n },\n // Social Links\n {\n name: "socialLinks",\n type: "group",\n label: "Social Links",\n admin: {\n description: "Add your social media profile URLs",\n },\n fields: [\n {\n name: "twitter",\n type: "text",\n label: "X (Twitter)",\n admin: {\n placeholder: "https://x.com/yourhandle",\n },\n },\n {\n name: "instagram",\n type: "text",\n label: "Instagram",\n admin: {\n placeholder: "https://instagram.com/yourhandle",\n },\n },\n {\n name: "linkedin",\n type: "text",\n label: "LinkedIn",\n admin: {\n placeholder: "https://linkedin.com/company/yourcompany",\n },\n },\n {\n name: "github",\n type: "text",\n label: "GitHub",\n admin: {\n placeholder: "https://github.com/yourorg",\n },\n },\n {\n name: "youtube",\n type: "text",\n label: "YouTube",\n admin: {\n placeholder: "https://youtube.com/@yourchannel",\n },\n },\n ],\n },\n // Newsletter Section\n {\n name: "newsletter",\n type: "group",\n label: "Newsletter",\n admin: {\n description: "Configure the newsletter signup section",\n },\n fields: [\n {\n name: "enabled",\n type: "checkbox",\n label: "Enable Newsletter Signup",\n defaultValue: true,\n },\n {\n name: "title",\n type: "text",\n label: "Title",\n defaultValue: "Newsletter",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n {\n name: "description",\n type: "textarea",\n label: "Description",\n defaultValue: "Stay up to date with the latest updates and news.",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n {\n name: "buttonText",\n type: "text",\n label: "Button Text",\n defaultValue: "Subscribe",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n {\n name: "placeholder",\n type: "text",\n label: "Email Placeholder",\n defaultValue: "Enter your email",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n ],\n },\n // Copyright and Bottom Bar\n {\n name: "copyrightText",\n type: "text",\n label: "Copyright Text",\n defaultValue: "{{projectName}}",\n admin: {\n description: "Company name for copyright (year is added automatically)",\n },\n },\n {\n name: "bottomLinks",\n type: "array",\n label: "Bottom Bar Links",\n maxRows: 4,\n admin: {\n description: "Links shown in the bottom bar (e.g., Contact Support, Privacy Policy)",\n initCollapsed: true,\n },\n fields: [\n link({\n appearances: false,\n }),\n ],\n },\n ],\n hooks: {\n afterChange: [revalidateFooter],\n },\n}\n',
583
+ "marketing/payload/src/Footer/hooks/revalidateFooter.ts.hbs": 'import type { GlobalAfterChangeHook } from "payload"\n\nimport { revalidateTag } from "next/cache"\n\nexport const revalidateFooter: GlobalAfterChangeHook = ({ doc, req: { payload, context } }) => {\n if (!context.disableRevalidate) {\n payload.logger.info("Revalidating footer")\n\n revalidateTag("global_footer")\n }\n\n return doc\n}\n',
584
+ "marketing/payload/src/Footer/index.ts.hbs": 'export { Footer } from "./config"\n',
585
+ "marketing/payload/src/Header/RowLabel.tsx.hbs": '"use client"\nimport type { Header } from "@/payload-types"\nimport { type RowLabelProps, useRowLabel } from "@payloadcms/ui"\n\nexport const RowLabel: React.FC<RowLabelProps> = () => {\n const data = useRowLabel<NonNullable<Header["navItems"]>[number]>()\n\n const itemLabel = data?.data?.label\n const itemType = data?.data?.type === "megaMenu" ? "Mega Menu" : "Link"\n const isRight = (data?.data?.position || "left") === "right"\n const itemPosition = isRight ? "Right" : "Left"\n const itemAppearance = isRight\n ? ` \xB7 ${(data?.data?.appearance || "button") === "button" ? "Button" : "Link"}`\n : ""\n\n const label = itemLabel\n ? `${data.rowNumber !== undefined ? data.rowNumber + 1 : ""}. ${itemLabel} \u2014 ${itemType} (${itemPosition}${itemAppearance})`\n : "Row"\n\n return <div>{label}</div>\n}\n',
586
+ "marketing/payload/src/Header/config.ts.hbs": 'import type { GlobalConfig } from "payload"\n\nimport { link } from "@/fields/link"\nimport { revalidateHeader } from "./hooks/revalidateHeader"\n\nexport const Header: GlobalConfig = {\n slug: "header",\n access: {\n read: () => true,\n },\n fields: [\n {\n name: "navItems",\n type: "array",\n maxRows: 8,\n admin: {\n initCollapsed: true,\n components: {\n RowLabel: "@/Header/RowLabel#RowLabel",\n },\n },\n fields: [\n {\n name: "type",\n type: "select",\n defaultValue: "link",\n options: [\n { label: "Simple Link", value: "link" },\n { label: "Mega Menu", value: "megaMenu" },\n ],\n admin: {\n description: "Choose between a simple link or a mega menu dropdown",\n },\n },\n {\n name: "label",\n type: "text",\n required: true,\n label: "Nav Item Label",\n },\n {\n name: "position",\n type: "select",\n defaultValue: "left",\n options: [\n { label: "Left (Near Logo)", value: "left" },\n { label: "Right (CTA Section)", value: "right" },\n ],\n admin: {\n description: "Control where this nav item appears in the header",\n },\n },\n {\n name: "appearance",\n type: "select",\n defaultValue: "button",\n options: [\n { label: "Button", value: "button" },\n { label: "Link", value: "link" },\n ],\n admin: {\n description: "How this item should be displayed",\n condition: (_, siblingData) => siblingData?.position === "right",\n },\n },\n // Simple link fields\n link({\n appearances: false,\n disableLabel: true,\n overrides: {\n admin: {\n condition: (_, siblingData) => siblingData?.type === "link",\n },\n },\n }),\n // Mega menu fields\n {\n name: "megaMenuColumns",\n type: "array",\n label: "Menu Columns",\n maxRows: 4,\n admin: {\n condition: (_, siblingData) => siblingData?.type === "megaMenu",\n },\n fields: [\n {\n name: "columnLabel",\n type: "text",\n label: "Column Heading",\n },\n {\n name: "columnDescription",\n type: "textarea",\n label: "Column Description",\n admin: {\n description: "Optional description shown below the column heading",\n },\n },\n {\n name: "items",\n type: "array",\n label: "Menu Items",\n maxRows: 8,\n fields: [\n {\n name: "label",\n type: "text",\n required: true,\n label: "Item Label",\n },\n {\n name: "description",\n type: "text",\n label: "Item Description",\n admin: {\n description: "Short description shown below the label",\n },\n },\n {\n name: "icon",\n type: "select",\n label: "Icon",\n options: [\n { label: "None", value: "none" },\n { label: "Layout", value: "layout" },\n { label: "Dollar Sign", value: "dollarSign" },\n { label: "Search", value: "search" },\n { label: "Settings", value: "settings" },\n { label: "Zap", value: "zap" },\n { label: "Layers", value: "layers" },\n { label: "Users", value: "users" },\n { label: "Building", value: "building" },\n { label: "Globe", value: "globe" },\n { label: "Store", value: "store" },\n { label: "Rocket", value: "rocket" },\n { label: "Target", value: "target" },\n { label: "BarChart", value: "barChart" },\n { label: "Shield", value: "shield" },\n { label: "Database", value: "database" },\n ],\n defaultValue: "none",\n },\n link({\n appearances: false,\n disableLabel: true,\n }),\n ],\n },\n ],\n },\n // Featured section for mega menu\n {\n name: "featuredItem",\n type: "group",\n label: "Featured Section",\n admin: {\n condition: (_, siblingData) => siblingData?.type === "megaMenu",\n description: "Optional featured content shown in the mega menu",\n },\n fields: [\n {\n name: "enabled",\n type: "checkbox",\n label: "Show Featured Section",\n defaultValue: false,\n },\n {\n name: "heading",\n type: "text",\n label: "Featured Heading",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n {\n name: "description",\n type: "textarea",\n label: "Featured Description",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n {\n name: "image",\n type: "upload",\n relationTo: "media",\n label: "Featured Image",\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n link({\n appearances: false,\n overrides: {\n admin: {\n condition: (_, siblingData) => siblingData?.enabled,\n },\n },\n }),\n ],\n },\n ],\n },\n ],\n hooks: {\n afterChange: [revalidateHeader],\n },\n}\n',
587
+ "marketing/payload/src/Header/hooks/revalidateHeader.ts.hbs": 'import type { GlobalAfterChangeHook } from "payload"\n\nimport { revalidateTag } from "next/cache"\n\nexport const revalidateHeader: GlobalAfterChangeHook = ({ doc, req: { payload, context } }) => {\n if (!context.disableRevalidate) {\n payload.logger.info("Revalidating header")\n\n revalidateTag("global_header")\n }\n\n return doc\n}\n',
588
+ "marketing/payload/src/Header/index.ts.hbs": 'export { Header } from "./config"\n',
589
+ "marketing/payload/src/access/anyone.ts.hbs": 'import type { Access } from "payload"\n\nexport const anyone: Access = () => true\n',
590
+ "marketing/payload/src/access/authenticated.ts.hbs": 'import type { AccessArgs } from "payload"\n\nimport type { User } from "@/payload-types"\n\ntype isAuthenticated = (args: AccessArgs<User>) => boolean\n\nexport const authenticated: isAuthenticated = ({ req: { user } }) => {\n return Boolean(user)\n}\n',
591
+ "marketing/payload/src/access/authenticatedOrPublished.ts.hbs": 'import type { Access } from "payload"\n\nexport const authenticatedOrPublished: Access = ({ req: { user } }) => {\n if (user) {\n return true\n }\n\n return {\n _status: {\n equals: "published",\n },\n }\n}\n',
592
+ "marketing/payload/src/access/index.ts.hbs": 'export { anyone } from "./anyone"\nexport { authenticated } from "./authenticated"\nexport { authenticatedOrPublished } from "./authenticatedOrPublished"\n',
582
593
  "marketing/payload/src/app/(frontend)/layout.tsx.hbs": `import type { Metadata } from 'next'
583
594
  import '../globals.css'
584
595
 
@@ -599,6 +610,7 @@ export default function FrontendLayout({
599
610
  )
600
611
  }
601
612
  `,
613
+ "marketing/payload/src/app/(frontend)/next/seed/route.ts.hbs": 'import { seed } from "@/endpoints/seed"\nimport config from "@payload-config"\nimport { headers } from "next/headers"\nimport { createLocalReq, getPayload } from "payload"\n\nexport const maxDuration = 60 // This function can run for a maximum of 60 seconds\n\nexport async function POST(): Promise<Response> {\n const payload = await getPayload({ config })\n const requestHeaders = await headers()\n\n // Authenticate by passing request headers\n const { user } = await payload.auth({ headers: requestHeaders })\n\n if (!user) {\n return new Response("Action forbidden.", { status: 403 })\n }\n\n try {\n // Create a Payload request object to pass to the Local API for transactions\n // At this point you should pass in a user, locale, and any other context you need for the Local API\n const payloadReq = await createLocalReq({ user }, payload)\n\n await seed({ payload, req: payloadReq })\n\n return Response.json({ success: true })\n } catch (e) {\n payload.logger.error({ err: e, message: "Error seeding data" })\n return new Response("Error seeding data.", { status: 500 })\n }\n}\n',
602
614
  "marketing/payload/src/app/(frontend)/page.tsx.hbs": `import { getPayload } from 'payload'
603
615
  import config from '@/payload.config'
604
616
 
@@ -683,14 +695,14 @@ export default async function HomePage() {
683
695
  }
684
696
  }
685
697
  `,
686
- "marketing/payload/src/app/(payload)/admin/[[...segments]]/not-found.tsx.hbs": "import config from '@/payload.config'\nimport { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'\nimport { importMap } from '../importMap.js'\nimport type { Metadata } from 'next'\n\ntype Args = {\n params: Promise<{ segments: string[] }>\n searchParams: Promise<Record<string, string | string[]>>\n}\n\nexport const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>\n generatePageMetadata({ config, params, searchParams })\n\nconst NotFound = ({ params, searchParams }: Args) =>\n NotFoundPage({ config, importMap, params, searchParams })\n\nexport default NotFound\n",
687
- "marketing/payload/src/app/(payload)/admin/[[...segments]]/page.tsx.hbs": "import config from '@/payload.config'\nimport { RootPage, generatePageMetadata } from '@payloadcms/next/views'\nimport { importMap } from '../importMap.js'\nimport type { Metadata } from 'next'\n\ntype Args = {\n params: Promise<{ segments: string[] }>\n searchParams: Promise<Record<string, string | string[]>>\n}\n\nexport const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>\n generatePageMetadata({ config, params, searchParams })\n\nconst Page = ({ params, searchParams }: Args) =>\n RootPage({ config, importMap, params, searchParams })\n\nexport default Page\n",
698
+ "marketing/payload/src/app/(payload)/admin/[[...segments]]/not-found.tsx.hbs": "/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */\n/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */\nimport type { Metadata } from 'next'\n\nimport config from '@payload-config'\nimport { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'\nimport { importMap } from '../importMap'\n\ntype Args = {\n params: Promise<{\n segments: string[]\n }>\n searchParams: Promise<{\n [key: string]: string | string[]\n }>\n}\n\nexport const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>\n generatePageMetadata({ config, params, searchParams })\n\nconst NotFound = ({ params, searchParams }: Args) =>\n NotFoundPage({ config, params, searchParams, importMap })\n\nexport default NotFound\n",
699
+ "marketing/payload/src/app/(payload)/admin/[[...segments]]/page.tsx.hbs": "/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */\n/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */\nimport type { Metadata } from 'next'\n\nimport config from '@payload-config'\nimport { RootPage, generatePageMetadata } from '@payloadcms/next/views'\nimport { importMap } from '../importMap'\n\ntype Args = {\n params: Promise<{\n segments: string[]\n }>\n searchParams: Promise<{\n [key: string]: string | string[]\n }>\n}\n\nexport const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>\n generatePageMetadata({ config, params, searchParams })\n\nconst Page = ({ params, searchParams }: Args) =>\n RootPage({ config, params, searchParams, importMap })\n\nexport default Page\n",
688
700
  "marketing/payload/src/app/(payload)/admin/importMap.js.hbs": "export const importMap = {}\n",
689
- "marketing/payload/src/app/(payload)/api/[...slug]/route.ts.hbs": "import config from '@/payload.config'\nimport { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes'\nimport { importMap } from '../../importMap.js'\n\nexport const GET = REST_GET(config, importMap)\nexport const POST = REST_POST(config, importMap)\nexport const DELETE = REST_DELETE(config, importMap)\nexport const PATCH = REST_PATCH(config, importMap)\nexport const OPTIONS = REST_OPTIONS(config)\n",
690
- "marketing/payload/src/app/(payload)/api/graphql/route.ts.hbs": "import config from '@/payload.config'\nimport { GRAPHQL_POST } from '@payloadcms/next/routes'\nimport { importMap } from '../../importMap.js'\n\nexport const POST = GRAPHQL_POST(config, importMap)\n",
691
- "marketing/payload/src/app/(payload)/api/graphql-playground/route.ts.hbs": "import config from '@/payload.config'\nimport { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'\nimport { importMap } from '../../importMap.js'\n\nexport const GET = GRAPHQL_PLAYGROUND_GET(config, importMap)\n",
701
+ "marketing/payload/src/app/(payload)/api/[...slug]/route.ts.hbs": "/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */\n/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */\nimport config from '@payload-config'\nimport '@payloadcms/next/css'\nimport {\n REST_DELETE,\n REST_GET,\n REST_OPTIONS,\n REST_PATCH,\n REST_POST,\n REST_PUT,\n} from '@payloadcms/next/routes'\n\nexport const GET = REST_GET(config)\nexport const POST = REST_POST(config)\nexport const DELETE = REST_DELETE(config)\nexport const PATCH = REST_PATCH(config)\nexport const PUT = REST_PUT(config)\nexport const OPTIONS = REST_OPTIONS(config)\n",
702
+ "marketing/payload/src/app/(payload)/api/graphql/route.ts.hbs": "/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */\n/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */\nimport config from '@payload-config'\nimport { GRAPHQL_POST, REST_OPTIONS } from '@payloadcms/next/routes'\n\nexport const POST = GRAPHQL_POST(config)\n\nexport const OPTIONS = REST_OPTIONS(config)\n",
703
+ "marketing/payload/src/app/(payload)/api/graphql-playground/route.ts.hbs": "/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */\n/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */\nimport config from '@payload-config'\nimport '@payloadcms/next/css'\nimport { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'\n\nexport const GET = GRAPHQL_PLAYGROUND_GET(config)\n",
692
704
  "marketing/payload/src/app/(payload)/custom.scss.hbs": "/* Custom Payload admin styles */\n",
693
- "marketing/payload/src/app/(payload)/layout.tsx.hbs": "import type { Metadata } from 'next'\nimport config from '@/payload.config'\nimport '@payloadcms/next/css'\nimport { RootLayout, handleServerFunctions } from '@payloadcms/next/layouts'\nimport type { ServerFunctionClient } from 'payload'\nimport { importMap } from './admin/importMap.js'\nimport './custom.scss'\n\nexport const metadata: Metadata = {\n title: 'Admin Panel',\n}\n\nconst serverFunction: ServerFunctionClient = async function (args) {\n 'use server'\n return handleServerFunctions({ ...args, config, importMap })\n}\n\nexport default async function Layout({ children }: { children: React.ReactNode }) {\n return (\n <RootLayout config={config} importMap={importMap} serverFunction={serverFunction}>\n {children}\n </RootLayout>\n )\n}\n",
705
+ "marketing/payload/src/app/(payload)/layout.tsx.hbs": "/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */\n/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */\nimport config from '@payload-config'\nimport '@payloadcms/next/css'\nimport { RootLayout, handleServerFunctions } from '@payloadcms/next/layouts'\nimport type { ServerFunctionClient } from 'payload'\nimport type React from 'react'\n\nimport { importMap } from './admin/importMap.js'\nimport './custom.scss'\n\ntype Args = {\n children: React.ReactNode\n}\n\nconst serverFunction: ServerFunctionClient = async (args) => {\n 'use server'\n return handleServerFunctions({\n ...args,\n config,\n importMap,\n })\n}\n\nconst Layout = ({ children }: Args) => (\n <RootLayout config={config} importMap={importMap} serverFunction={serverFunction}>\n {children}\n </RootLayout>\n)\n\nexport default Layout\n",
694
706
  "marketing/payload/src/app/globals.css.hbs": '@import "tailwindcss";\n\n@custom-variant dark (&:is(.dark *));\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --font-sans: var(--font-geist-sans);\n --font-mono: var(--font-geist-mono);\n --color-ring: var(--ring);\n --color-input: var(--input);\n --color-border: var(--border);\n --color-destructive: var(--destructive);\n --color-accent-foreground: var(--accent-foreground);\n --color-accent: var(--accent);\n --color-muted-foreground: var(--muted-foreground);\n --color-muted: var(--muted);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-secondary: var(--secondary);\n --color-primary-foreground: var(--primary-foreground);\n --color-primary: var(--primary);\n --color-popover-foreground: var(--popover-foreground);\n --color-popover: var(--popover);\n --color-card-foreground: var(--card-foreground);\n --color-card: var(--card);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n}\n\n:root {\n --radius: 0.625rem;\n --background: oklch(1 0 0);\n --foreground: oklch(0.145 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.145 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.145 0 0);\n --primary: oklch(0.205 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.97 0 0);\n --secondary-foreground: oklch(0.205 0 0);\n --muted: oklch(0.97 0 0);\n --muted-foreground: oklch(0.556 0 0);\n --accent: oklch(0.97 0 0);\n --accent-foreground: oklch(0.205 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.922 0 0);\n --input: oklch(0.922 0 0);\n --ring: oklch(0.708 0 0);\n}\n\n.dark {\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.205 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.269 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n --ring: oklch(0.556 0 0);\n}\n\n@layer base {\n * {\n @apply border-border outline-ring/50;\n }\n\n body {\n @apply bg-background text-foreground;\n }\n}\n',
695
707
  "marketing/payload/src/app/layout.tsx.hbs": "// Root layout is minimal - each route group has its own complete layout\n// This prevents nested <html>/<body> tags between frontend and Payload admin\n// CSS is imported in each route group's layout to avoid style conflicts\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode\n}) {\n return children\n}\n",
696
708
  "marketing/payload/src/blocks/Benefits.ts.hbs": "import type { Block } from 'payload'\n\nexport const BenefitsBlock: Block = {\n slug: 'benefits',\n labels: { singular: 'Benefits', plural: 'Benefits' },\n fields: [\n { name: 'label', type: 'text' },\n { name: 'heading', type: 'text', required: true },\n { name: 'description', type: 'textarea' },\n { name: 'image', type: 'upload', relationTo: 'media' },\n {\n name: 'imagePosition',\n type: 'select',\n options: [\n { label: 'Left', value: 'left' },\n { label: 'Right', value: 'right' },\n ],\n defaultValue: 'right',\n },\n {\n name: 'benefits',\n type: 'array',\n fields: [{ name: 'text', type: 'text', required: true }],\n },\n {\n name: 'cta',\n type: 'group',\n fields: [\n { name: 'label', type: 'text' },\n { name: 'url', type: 'text' },\n ],\n },\n ],\n}\n",
@@ -703,16 +715,331 @@ export default async function HomePage() {
703
715
  "marketing/payload/src/blocks/Pricing.ts.hbs": "import type { Block } from 'payload'\n\nexport const PricingBlock: Block = {\n slug: 'pricing',\n labels: { singular: 'Pricing', plural: 'Pricing' },\n fields: [\n { name: 'heading', type: 'text' },\n { name: 'subheading', type: 'textarea' },\n {\n name: 'plans',\n type: 'array',\n fields: [\n { name: 'name', type: 'text', required: true },\n { name: 'price', type: 'text', required: true },\n { name: 'period', type: 'text', defaultValue: '/month' },\n { name: 'description', type: 'textarea' },\n { name: 'featured', type: 'checkbox', defaultValue: false },\n {\n name: 'features',\n type: 'array',\n fields: [\n { name: 'feature', type: 'text', required: true },\n { name: 'included', type: 'checkbox', defaultValue: true },\n ],\n },\n {\n name: 'cta',\n type: 'group',\n fields: [\n { name: 'label', type: 'text' },\n { name: 'url', type: 'text' },\n ],\n },\n ],\n },\n ],\n}\n",
704
716
  "marketing/payload/src/blocks/Testimonials.ts.hbs": "import type { Block } from 'payload'\n\nexport const TestimonialsBlock: Block = {\n slug: 'testimonials',\n labels: { singular: 'Testimonials', plural: 'Testimonials' },\n fields: [\n { name: 'heading', type: 'text' },\n { name: 'subheading', type: 'textarea' },\n {\n name: 'testimonials',\n type: 'array',\n fields: [\n { name: 'quote', type: 'textarea', required: true },\n { name: 'author', type: 'text', required: true },\n { name: 'role', type: 'text' },\n { name: 'company', type: 'text' },\n { name: 'image', type: 'upload', relationTo: 'media' },\n ],\n },\n ],\n}\n",
705
717
  "marketing/payload/src/blocks/index.ts.hbs": "export { HeroBlock } from './Hero'\nexport { LogoBannerBlock } from './LogoBanner'\nexport { FeaturesBlock } from './Features'\nexport { BenefitsBlock } from './Benefits'\nexport { PricingBlock } from './Pricing'\nexport { TestimonialsBlock } from './Testimonials'\nexport { FAQBlock } from './FAQ'\nexport { ContentBlock } from './Content'\nexport { CTABlock } from './CTA'\n",
706
- "marketing/payload/src/collections/Media.ts.hbs": "import type { CollectionConfig } from 'payload'\n\nexport const Media: CollectionConfig = {\n slug: 'media',\n access: {\n read: () => true,\n },\n upload: {\n staticDir: 'media',\n imageSizes: [\n {\n name: 'thumbnail',\n width: 400,\n height: 300,\n position: 'centre',\n },\n {\n name: 'card',\n width: 768,\n height: 432,\n position: 'centre',\n },\n {\n name: 'hero',\n width: 1920,\n height: 1080,\n position: 'centre',\n },\n ],\n adminThumbnail: 'thumbnail',\n mimeTypes: ['image/*'],\n },\n fields: [\n {\n name: 'alt',\n type: 'text',\n required: true,\n },\n {\n name: 'caption',\n type: 'text',\n },\n ],\n}\n",
707
- "marketing/payload/src/collections/Pages.ts.hbs": "import type { CollectionConfig } from 'payload'\nimport {\n HeroBlock,\n LogoBannerBlock,\n FeaturesBlock,\n BenefitsBlock,\n PricingBlock,\n TestimonialsBlock,\n FAQBlock,\n ContentBlock,\n CTABlock,\n} from '../blocks'\n\nexport const Pages: CollectionConfig = {\n slug: 'pages',\n admin: {\n useAsTitle: 'title',\n defaultColumns: ['title', 'slug', 'status', 'updatedAt'],\n },\n access: {\n read: () => true,\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n required: true,\n },\n {\n name: 'slug',\n type: 'text',\n required: true,\n unique: true,\n admin: {\n position: 'sidebar',\n },\n },\n {\n name: 'status',\n type: 'select',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Published', value: 'published' },\n ],\n defaultValue: 'draft',\n admin: {\n position: 'sidebar',\n },\n },\n {\n name: 'layout',\n type: 'blocks',\n blocks: [\n HeroBlock,\n LogoBannerBlock,\n FeaturesBlock,\n BenefitsBlock,\n PricingBlock,\n TestimonialsBlock,\n FAQBlock,\n ContentBlock,\n CTABlock,\n ],\n },\n ],\n}\n",
708
- "marketing/payload/src/collections/Posts.ts.hbs": "import type { CollectionConfig } from 'payload'\n\nexport const Posts: CollectionConfig = {\n slug: 'posts',\n admin: {\n useAsTitle: 'title',\n defaultColumns: ['title', 'author', 'status', 'publishedAt'],\n },\n access: {\n read: () => true,\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n required: true,\n },\n {\n name: 'slug',\n type: 'text',\n required: true,\n unique: true,\n },\n {\n name: 'excerpt',\n type: 'textarea',\n },\n {\n name: 'content',\n type: 'richText',\n },\n {\n name: 'featuredImage',\n type: 'upload',\n relationTo: 'media',\n },\n {\n name: 'author',\n type: 'relationship',\n relationTo: 'users',\n admin: {\n position: 'sidebar',\n },\n },\n {\n name: 'status',\n type: 'select',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Published', value: 'published' },\n ],\n defaultValue: 'draft',\n admin: {\n position: 'sidebar',\n },\n },\n {\n name: 'publishedAt',\n type: 'date',\n admin: {\n position: 'sidebar',\n },\n },\n ],\n}\n",
709
- "marketing/payload/src/collections/Users.ts.hbs": "import type { CollectionConfig } from 'payload'\n\nexport const Users: CollectionConfig = {\n slug: 'users',\n admin: {\n useAsTitle: 'email',\n },\n auth: true,\n fields: [\n {\n name: 'name',\n type: 'text',\n },\n {\n name: 'role',\n type: 'select',\n options: [\n { label: 'Admin', value: 'admin' },\n { label: 'Editor', value: 'editor' },\n ],\n defaultValue: 'editor',\n required: true,\n },\n ],\n}\n",
710
- "marketing/payload/src/collections/index.ts.hbs": "export { Users } from './Users'\nexport { Media } from './Media'\nexport { Pages } from './Pages'\nexport { Posts } from './Posts'\n",
711
- "marketing/payload/src/globals/Navigation.ts.hbs": "import type { GlobalConfig } from 'payload'\n\nexport const Navigation: GlobalConfig = {\n slug: 'navigation',\n access: {\n read: () => true,\n },\n fields: [\n {\n name: 'items',\n type: 'array',\n fields: [\n {\n name: 'label',\n type: 'text',\n required: true,\n },\n {\n name: 'link',\n type: 'group',\n fields: [\n {\n name: 'type',\n type: 'radio',\n options: [\n { label: 'Internal', value: 'internal' },\n { label: 'External', value: 'external' },\n ],\n defaultValue: 'internal',\n },\n {\n name: 'page',\n type: 'relationship',\n relationTo: 'pages',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'internal',\n },\n },\n {\n name: 'url',\n type: 'text',\n admin: {\n condition: (_, siblingData) => siblingData?.type === 'external',\n },\n },\n ],\n },\n ],\n },\n ],\n}\n",
712
- "marketing/payload/src/globals/SiteSettings.ts.hbs": "import type { GlobalConfig } from 'payload'\n\nexport const SiteSettings: GlobalConfig = {\n slug: 'site-settings',\n access: {\n read: () => true,\n },\n fields: [\n {\n name: 'siteName',\n type: 'text',\n required: true,\n },\n {\n name: 'siteDescription',\n type: 'textarea',\n },\n {\n name: 'logo',\n type: 'upload',\n relationTo: 'media',\n },\n {\n name: 'favicon',\n type: 'upload',\n relationTo: 'media',\n },\n {\n name: 'socialLinks',\n type: 'array',\n fields: [\n {\n name: 'platform',\n type: 'select',\n options: [\n { label: 'Twitter', value: 'twitter' },\n { label: 'GitHub', value: 'github' },\n { label: 'LinkedIn', value: 'linkedin' },\n { label: 'Discord', value: 'discord' },\n ],\n },\n {\n name: 'url',\n type: 'text',\n },\n ],\n },\n ],\n}\n",
713
- "marketing/payload/src/globals/index.ts.hbs": "export { SiteSettings } from './SiteSettings'\nexport { Navigation } from './Navigation'\n",
714
- "marketing/payload/src/payload.config.ts.hbs": "import path from 'path'\nimport { fileURLToPath } from 'url'\nimport { buildConfig } from 'payload'\nimport { postgresAdapter } from '@payloadcms/db-postgres'\nimport { lexicalEditor } from '@payloadcms/richtext-lexical'\nimport { seoPlugin } from '@payloadcms/plugin-seo'\nimport { resendAdapter } from '@payloadcms/email-resend'\nimport sharp from 'sharp'\n{{#if (eq integrations.payloadStorage 's3')}}\nimport { s3Storage } from '@payloadcms/storage-s3'\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\nimport { s3Storage } from '@payloadcms/storage-s3'\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\nimport { vercelBlobStorage } from '@payloadcms/storage-vercel-blob'\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\nimport { gcsStorage } from '@payloadcms/storage-gcs'\n{{/if}}\n\nimport { Pages } from './collections/Pages'\nimport { Media } from './collections/Media'\nimport { Users } from './collections/Users'\nimport { Posts } from './collections/Posts'\nimport { SiteSettings } from './globals/SiteSettings'\nimport { Navigation } from './globals/Navigation'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nexport default buildConfig({\n admin: {\n user: Users.slug,\n importMap: {\n baseDir: path.resolve(__dirname),\n },\n },\n db: postgresAdapter({\n pool: {\n connectionString: process.env.DATABASE_URL,\n },\n }),\n editor: lexicalEditor(),\n email: resendAdapter({\n defaultFromAddress: process.env.RESEND_FROM_EMAIL || 'noreply@example.com',\n defaultFromName: '{{projectName}}',\n apiKey: process.env.RESEND_API_KEY || '',\n }),\n collections: [Users, Media, Pages, Posts],\n globals: [SiteSettings, Navigation],\n plugins: [\n{{#if (eq integrations.payloadStorage 's3')}}\n s3Storage({\n collections: {\n media: true,\n },\n bucket: process.env.S3_BUCKET!,\n config: {\n credentials: {\n accessKeyId: process.env.S3_ACCESS_KEY_ID!,\n secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,\n },\n region: process.env.S3_REGION!,\n endpoint: process.env.S3_ENDPOINT,\n forcePathStyle: true,\n },\n }),\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\n s3Storage({\n collections: {\n media: true,\n },\n bucket: process.env.R2_BUCKET!,\n config: {\n credentials: {\n accessKeyId: process.env.R2_ACCESS_KEY_ID!,\n secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,\n },\n region: 'auto',\n endpoint: process.env.R2_ENDPOINT!,\n forcePathStyle: true,\n },\n }),\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\n vercelBlobStorage({\n collections: {\n media: true,\n },\n token: process.env.BLOB_READ_WRITE_TOKEN!,\n }),\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\n gcsStorage({\n collections: {\n media: true,\n },\n bucket: process.env.GCS_BUCKET!,\n options: {\n projectId: process.env.GCS_PROJECT_ID,\n credentials: JSON.parse(process.env.GCS_CREDENTIALS || '{}'),\n },\n }),\n{{/if}}\n seoPlugin({\n collections: ['pages', 'posts'],\n uploadsCollection: 'media',\n generateTitle: ({ doc }) => `${doc?.title ?? ''} | {{projectName}}`,\n generateDescription: ({ doc }) => doc?.excerpt ?? '',\n }),\n ],\n secret: process.env.PAYLOAD_SECRET!,\n sharp,\n typescript: {\n outputFile: path.resolve(__dirname, 'payload-types.ts'),\n },\n{{#if (eq integrations.payloadStorage 'local')}}\n upload: {\n limits: {\n fileSize: 5000000, // 5MB\n },\n },\n{{/if}}\n})\n",
715
- "marketing/payload/tsconfig.json.hbs": '{\n "compilerOptions": {\n "target": "ES2017",\n "lib": ["dom", "dom.iterable", "esnext"],\n "allowJs": true,\n "skipLibCheck": true,\n "strict": true,\n "noEmit": true,\n "esModuleInterop": true,\n "module": "esnext",\n "moduleResolution": "bundler",\n "resolveJsonModule": true,\n "isolatedModules": true,\n "jsx": "preserve",\n "incremental": true,\n "plugins": [{ "name": "next" }],\n "paths": {\n "@/*": ["./src/*"]\n }\n },\n "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],\n "exclude": ["node_modules"]\n}\n',
718
+ "marketing/payload/src/collections/Categories/index.ts.hbs": 'import type { CollectionConfig } from "payload"\n\nimport { slugField } from "payload"\nimport { anyone } from "../../access/anyone"\nimport { authenticated } from "../../access/authenticated"\n\nexport const Categories: CollectionConfig = {\n slug: "categories",\n access: {\n create: authenticated,\n delete: authenticated,\n read: anyone,\n update: authenticated,\n },\n admin: {\n useAsTitle: "title",\n },\n fields: [\n {\n name: "title",\n type: "text",\n required: true,\n },\n slugField({\n position: undefined,\n }),\n ],\n}\n',
719
+ "marketing/payload/src/collections/FAQs/index.ts.hbs": 'import type { CollectionConfig } from "payload"\n\nimport {\n AlignFeature,\n BlockquoteFeature,\n ChecklistFeature,\n EXPERIMENTAL_TableFeature,\n FixedToolbarFeature,\n IndentFeature,\n InlineCodeFeature,\n InlineToolbarFeature,\n OrderedListFeature,\n RelationshipFeature,\n StrikethroughFeature,\n SubscriptFeature,\n SuperscriptFeature,\n UnorderedListFeature,\n UploadFeature,\n lexicalEditor,\n} from "@payloadcms/richtext-lexical"\nimport { anyone } from "../../access/anyone"\nimport { authenticated } from "../../access/authenticated"\n\nexport const FAQs: CollectionConfig = {\n slug: "faqs",\n access: {\n create: authenticated,\n delete: authenticated,\n read: anyone,\n update: authenticated,\n },\n admin: {\n useAsTitle: "question",\n defaultColumns: ["question", "category", "order", "updatedAt"],\n group: "Content",\n },\n fields: [\n {\n name: "question",\n type: "text",\n required: true,\n label: "Question",\n },\n {\n name: "answer",\n type: "richText",\n required: true,\n label: "Answer",\n editor: lexicalEditor({\n features: ({ rootFeatures }) => {\n return [\n ...rootFeatures,\n FixedToolbarFeature(),\n InlineToolbarFeature(),\n StrikethroughFeature(),\n SubscriptFeature(),\n SuperscriptFeature(),\n InlineCodeFeature(),\n BlockquoteFeature(),\n UnorderedListFeature(),\n OrderedListFeature(),\n ChecklistFeature(),\n AlignFeature(),\n IndentFeature(),\n RelationshipFeature(),\n UploadFeature(),\n EXPERIMENTAL_TableFeature(),\n ]\n },\n }),\n },\n {\n name: "category",\n type: "select",\n required: true,\n defaultValue: "general",\n options: [\n { label: "General", value: "general" },\n { label: "Pricing", value: "pricing" },\n { label: "Features", value: "features" },\n { label: "Getting Started", value: "getting-started" },\n { label: "Technical", value: "technical" },\n { label: "Support", value: "support" },\n ],\n admin: {\n position: "sidebar",\n },\n },\n {\n name: "order",\n type: "number",\n defaultValue: 0,\n admin: {\n position: "sidebar",\n description: "Lower numbers appear first",\n },\n },\n ],\n defaultSort: "order",\n}\n',
720
+ "marketing/payload/src/collections/Media.ts.hbs": `import type { CollectionConfig } from "payload"
721
+
722
+ import path from "node:path"
723
+ import { fileURLToPath } from "node:url"
724
+ import {
725
+ AlignFeature,
726
+ BlockquoteFeature,
727
+ ChecklistFeature,
728
+ EXPERIMENTAL_TableFeature,
729
+ FixedToolbarFeature,
730
+ IndentFeature,
731
+ InlineCodeFeature,
732
+ InlineToolbarFeature,
733
+ OrderedListFeature,
734
+ RelationshipFeature,
735
+ StrikethroughFeature,
736
+ SubscriptFeature,
737
+ SuperscriptFeature,
738
+ UnorderedListFeature,
739
+ UploadFeature,
740
+ lexicalEditor,
741
+ } from "@payloadcms/richtext-lexical"
742
+
743
+ import { anyone } from "../access/anyone"
744
+ import { authenticated } from "../access/authenticated"
745
+
746
+ const filename = fileURLToPath(import.meta.url)
747
+ const dirname = path.dirname(filename)
748
+
749
+ {{#if (eq integrations.payloadStorage 'local')}}
750
+ // Local storage configuration
751
+ const useLocalStorage = true
752
+ {{else}}
753
+ // Only use local staticDir when storage token is not set (local development)
754
+ // In production, cloud storage handles file storage
755
+ const useLocalStorage = !process.env.BLOB_READ_WRITE_TOKEN && !process.env.S3_BUCKET && !process.env.R2_BUCKET && !process.env.GCS_BUCKET
756
+ {{/if}}
757
+
758
+ export const Media: CollectionConfig = {
759
+ slug: "media",
760
+ folders: true,
761
+ access: {
762
+ create: authenticated,
763
+ delete: authenticated,
764
+ read: anyone,
765
+ update: authenticated,
766
+ },
767
+ fields: [
768
+ {
769
+ name: "alt",
770
+ type: "text",
771
+ },
772
+ {
773
+ name: "caption",
774
+ type: "richText",
775
+ editor: lexicalEditor({
776
+ features: ({ rootFeatures }) => {
777
+ return [
778
+ ...rootFeatures,
779
+ FixedToolbarFeature(),
780
+ InlineToolbarFeature(),
781
+ StrikethroughFeature(),
782
+ SubscriptFeature(),
783
+ SuperscriptFeature(),
784
+ InlineCodeFeature(),
785
+ BlockquoteFeature(),
786
+ UnorderedListFeature(),
787
+ OrderedListFeature(),
788
+ ChecklistFeature(),
789
+ AlignFeature(),
790
+ IndentFeature(),
791
+ RelationshipFeature(),
792
+ UploadFeature(),
793
+ EXPERIMENTAL_TableFeature(),
794
+ ]
795
+ },
796
+ }),
797
+ },
798
+ ],
799
+ upload: {
800
+ // Only use local staticDir for development; production uses cloud storage
801
+ ...(useLocalStorage && {
802
+ staticDir: path.resolve(dirname, "../../public/media"),
803
+ }),
804
+ adminThumbnail: "thumbnail",
805
+ focalPoint: true,
806
+ // Allow common image and video file types
807
+ mimeTypes: [
808
+ "image/*",
809
+ "video/mp4",
810
+ "video/webm",
811
+ "video/quicktime", // .mov files
812
+ ],
813
+ // Convert original uploaded image to WebP format for better compression
814
+ // Note: formatOptions only applies to images, videos are uploaded as-is
815
+ formatOptions: {
816
+ format: "webp",
817
+ options: {
818
+ quality: 85,
819
+ },
820
+ },
821
+ imageSizes: [
822
+ {
823
+ name: "thumbnail",
824
+ width: 300,
825
+ formatOptions: {
826
+ format: "webp",
827
+ options: { quality: 80 },
828
+ },
829
+ },
830
+ {
831
+ name: "square",
832
+ width: 500,
833
+ height: 500,
834
+ formatOptions: {
835
+ format: "webp",
836
+ options: { quality: 80 },
837
+ },
838
+ },
839
+ {
840
+ name: "small",
841
+ width: 600,
842
+ formatOptions: {
843
+ format: "webp",
844
+ options: { quality: 80 },
845
+ },
846
+ },
847
+ {
848
+ name: "medium",
849
+ width: 900,
850
+ formatOptions: {
851
+ format: "webp",
852
+ options: { quality: 80 },
853
+ },
854
+ },
855
+ {
856
+ name: "large",
857
+ width: 1400,
858
+ formatOptions: {
859
+ format: "webp",
860
+ options: { quality: 80 },
861
+ },
862
+ },
863
+ {
864
+ name: "xlarge",
865
+ width: 1920,
866
+ formatOptions: {
867
+ format: "webp",
868
+ options: { quality: 80 },
869
+ },
870
+ },
871
+ {
872
+ name: "og",
873
+ width: 1200,
874
+ height: 630,
875
+ crop: "center",
876
+ formatOptions: {
877
+ format: "webp",
878
+ options: { quality: 85 },
879
+ },
880
+ },
881
+ ],
882
+ },
883
+ }
884
+ `,
885
+ "marketing/payload/src/collections/Pages/hooks/revalidatePage.ts.hbs": 'import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from "payload"\n\nimport { revalidatePath, revalidateTag } from "next/cache"\n\nimport type { Page } from "../../../payload-types"\n\nexport const revalidatePage: CollectionAfterChangeHook<Page> = ({\n doc,\n previousDoc,\n req: { payload, context },\n}) => {\n if (!context.disableRevalidate) {\n if (doc._status === "published") {\n const path = doc.slug === "home" ? "/" : `/${doc.slug}`\n\n payload.logger.info(`Revalidating page at path: ${path}`)\n\n revalidatePath(path)\n revalidateTag("pages-sitemap")\n }\n\n // If the page was previously published, we need to revalidate the old path\n if (previousDoc?._status === "published" && doc._status !== "published") {\n const oldPath = previousDoc.slug === "home" ? "/" : `/${previousDoc.slug}`\n\n payload.logger.info(`Revalidating old page at path: ${oldPath}`)\n\n revalidatePath(oldPath)\n revalidateTag("pages-sitemap")\n }\n }\n return doc\n}\n\nexport const revalidateDelete: CollectionAfterDeleteHook<Page> = ({ doc, req: { context } }) => {\n if (!context.disableRevalidate) {\n const path = doc?.slug === "home" ? "/" : `/${doc?.slug}`\n revalidatePath(path)\n revalidateTag("pages-sitemap")\n }\n\n return doc\n}\n',
886
+ "marketing/payload/src/collections/Pages/index.ts.hbs": 'import type { CollectionConfig } from "payload"\n\nimport { slugField } from "payload"\nimport { authenticated } from "../../access/authenticated"\nimport { authenticatedOrPublished } from "../../access/authenticatedOrPublished"\nimport { populatePublishedAt } from "../../hooks/populatePublishedAt"\nimport { generatePreviewPath } from "../../utilities/generatePreviewPath"\nimport { revalidateDelete, revalidatePage } from "./hooks/revalidatePage"\n\n// Import blocks\nimport {\n HeroBlock,\n LogoBannerBlock,\n FeaturesBlock,\n BenefitsBlock,\n PricingBlock,\n TestimonialsBlock,\n FAQBlock,\n ContentBlock,\n CTABlock,\n} from "../../blocks"\n\nimport {\n MetaDescriptionField,\n MetaImageField,\n MetaTitleField,\n OverviewField,\n PreviewField,\n} from "@payloadcms/plugin-seo/fields"\n\nexport const Pages: CollectionConfig<"pages"> = {\n slug: "pages",\n access: {\n create: authenticated,\n delete: authenticated,\n read: authenticatedOrPublished,\n update: authenticated,\n },\n defaultPopulate: {\n title: true,\n slug: true,\n },\n admin: {\n defaultColumns: ["title", "slug", "updatedAt"],\n livePreview: {\n url: ({ data, req }) =>\n generatePreviewPath({\n slug: data?.slug,\n collection: "pages",\n req,\n }),\n },\n preview: (data, { req }) =>\n generatePreviewPath({\n slug: data?.slug as string,\n collection: "pages",\n req,\n }),\n useAsTitle: "title",\n },\n fields: [\n {\n name: "title",\n type: "text",\n required: true,\n },\n {\n type: "tabs",\n tabs: [\n {\n fields: [\n {\n name: "layout",\n type: "blocks",\n blocks: [\n HeroBlock,\n LogoBannerBlock,\n FeaturesBlock,\n BenefitsBlock,\n PricingBlock,\n TestimonialsBlock,\n FAQBlock,\n ContentBlock,\n CTABlock,\n ],\n required: true,\n admin: {\n initCollapsed: true,\n },\n },\n ],\n label: "Content",\n },\n {\n name: "meta",\n label: "SEO",\n fields: [\n OverviewField({\n titlePath: "meta.title",\n descriptionPath: "meta.description",\n imagePath: "meta.image",\n }),\n MetaTitleField({\n hasGenerateFn: true,\n }),\n MetaImageField({\n relationTo: "media",\n }),\n MetaDescriptionField({}),\n PreviewField({\n hasGenerateFn: true,\n titlePath: "meta.title",\n descriptionPath: "meta.description",\n }),\n ],\n },\n ],\n },\n {\n name: "publishedAt",\n type: "date",\n admin: {\n position: "sidebar",\n },\n },\n slugField(),\n ],\n hooks: {\n afterChange: [revalidatePage],\n beforeChange: [populatePublishedAt],\n afterDelete: [revalidateDelete],\n },\n versions: {\n drafts: {\n autosave: {\n interval: 100,\n },\n schedulePublish: true,\n },\n maxPerDoc: 50,\n },\n}\n',
887
+ "marketing/payload/src/collections/Posts/hooks/populateAuthors.ts.hbs": 'import type { CollectionAfterReadHook } from "payload"\nimport type { User } from "src/payload-types"\n\n// The `user` collection has access control locked so that users are not publicly accessible\n// This means that we need to populate the authors manually here to protect user privacy\n// GraphQL will not return mutated user data that differs from the underlying schema\n// So we use an alternative `populatedAuthors` field to populate the user data, hidden from the admin UI\nexport const populateAuthors: CollectionAfterReadHook = async ({\n doc,\n req: _req,\n req: { payload },\n}) => {\n if (doc?.authors && doc?.authors?.length > 0) {\n const authorDocs: User[] = []\n\n for (const author of doc.authors) {\n try {\n const authorDoc = await payload.findByID({\n id: typeof author === "object" ? author?.id : author,\n collection: "users",\n depth: 0,\n })\n\n if (authorDoc) {\n authorDocs.push(authorDoc)\n }\n\n if (authorDocs.length > 0) {\n doc.populatedAuthors = authorDocs.map((authorDoc) => ({\n id: authorDoc.id,\n name: authorDoc.name,\n }))\n }\n } catch {\n // swallow error\n }\n }\n }\n\n return doc\n}\n',
888
+ "marketing/payload/src/collections/Posts/hooks/revalidatePost.ts.hbs": 'import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from "payload"\n\nimport { revalidatePath, revalidateTag } from "next/cache"\n\nimport type { Post } from "../../../payload-types"\n\nexport const revalidatePost: CollectionAfterChangeHook<Post> = ({\n doc,\n previousDoc,\n req: { payload, context },\n}) => {\n if (!context.disableRevalidate) {\n if (doc._status === "published") {\n const path = `/posts/${doc.slug}`\n\n payload.logger.info(`Revalidating post at path: ${path}`)\n\n revalidatePath(path)\n revalidateTag("posts-sitemap")\n }\n\n // If the post was previously published, we need to revalidate the old path\n if (previousDoc._status === "published" && doc._status !== "published") {\n const oldPath = `/posts/${previousDoc.slug}`\n\n payload.logger.info(`Revalidating old post at path: ${oldPath}`)\n\n revalidatePath(oldPath)\n revalidateTag("posts-sitemap")\n }\n }\n return doc\n}\n\nexport const revalidateDelete: CollectionAfterDeleteHook<Post> = ({ doc, req: { context } }) => {\n if (!context.disableRevalidate) {\n const path = `/posts/${doc?.slug}`\n\n revalidatePath(path)\n revalidateTag("posts-sitemap")\n }\n\n return doc\n}\n',
889
+ "marketing/payload/src/collections/Posts/index.ts.hbs": 'import type { CollectionConfig } from "payload"\n\nimport {\n AlignFeature,\n BlockquoteFeature,\n ChecklistFeature,\n EXPERIMENTAL_TableFeature,\n FixedToolbarFeature,\n HeadingFeature,\n HorizontalRuleFeature,\n IndentFeature,\n InlineCodeFeature,\n InlineToolbarFeature,\n OrderedListFeature,\n RelationshipFeature,\n StrikethroughFeature,\n SubscriptFeature,\n SuperscriptFeature,\n UnorderedListFeature,\n UploadFeature,\n lexicalEditor,\n} from "@payloadcms/richtext-lexical"\n\nimport { authenticated } from "../../access/authenticated"\nimport { authenticatedOrPublished } from "../../access/authenticatedOrPublished"\nimport { generatePreviewPath } from "../../utilities/generatePreviewPath"\nimport { populateAuthors } from "./hooks/populateAuthors"\nimport { revalidateDelete, revalidatePost } from "./hooks/revalidatePost"\n\nimport {\n MetaDescriptionField,\n MetaImageField,\n MetaTitleField,\n OverviewField,\n PreviewField,\n} from "@payloadcms/plugin-seo/fields"\nimport { slugField } from "payload"\n\nexport const Posts: CollectionConfig<"posts"> = {\n slug: "posts",\n access: {\n create: authenticated,\n delete: authenticated,\n read: authenticatedOrPublished,\n update: authenticated,\n },\n defaultPopulate: {\n title: true,\n slug: true,\n categories: true,\n meta: {\n image: true,\n description: true,\n },\n },\n admin: {\n defaultColumns: ["title", "slug", "updatedAt"],\n livePreview: {\n url: ({ data, req }) =>\n generatePreviewPath({\n slug: data?.slug,\n collection: "posts",\n req,\n }),\n },\n preview: (data, { req }) =>\n generatePreviewPath({\n slug: data?.slug as string,\n collection: "posts",\n req,\n }),\n useAsTitle: "title",\n },\n fields: [\n {\n name: "title",\n type: "text",\n required: true,\n },\n {\n type: "tabs",\n tabs: [\n {\n fields: [\n {\n name: "heroImage",\n type: "upload",\n relationTo: "media",\n },\n {\n name: "content",\n type: "richText",\n editor: lexicalEditor({\n features: ({ rootFeatures }) => {\n return [\n ...rootFeatures,\n HeadingFeature({ enabledHeadingSizes: ["h1", "h2", "h3", "h4"] }),\n FixedToolbarFeature(),\n InlineToolbarFeature(),\n HorizontalRuleFeature(),\n StrikethroughFeature(),\n SubscriptFeature(),\n SuperscriptFeature(),\n InlineCodeFeature(),\n BlockquoteFeature(),\n UnorderedListFeature(),\n OrderedListFeature(),\n ChecklistFeature(),\n AlignFeature(),\n IndentFeature(),\n RelationshipFeature(),\n UploadFeature(),\n EXPERIMENTAL_TableFeature(),\n ]\n },\n }),\n label: false,\n required: true,\n },\n ],\n label: "Content",\n },\n {\n fields: [\n {\n name: "relatedPosts",\n type: "relationship",\n admin: {\n position: "sidebar",\n },\n filterOptions: ({ id }) => {\n return {\n id: {\n not_in: [id],\n },\n }\n },\n hasMany: true,\n relationTo: "posts",\n },\n {\n name: "categories",\n type: "relationship",\n admin: {\n position: "sidebar",\n },\n hasMany: true,\n relationTo: "categories",\n },\n ],\n label: "Meta",\n },\n {\n name: "meta",\n label: "SEO",\n fields: [\n OverviewField({\n titlePath: "meta.title",\n descriptionPath: "meta.description",\n imagePath: "meta.image",\n }),\n MetaTitleField({\n hasGenerateFn: true,\n }),\n MetaImageField({\n relationTo: "media",\n }),\n MetaDescriptionField({}),\n PreviewField({\n hasGenerateFn: true,\n titlePath: "meta.title",\n descriptionPath: "meta.description",\n }),\n ],\n },\n ],\n },\n {\n name: "publishedAt",\n type: "date",\n admin: {\n date: {\n pickerAppearance: "dayAndTime",\n },\n position: "sidebar",\n },\n hooks: {\n beforeChange: [\n ({ siblingData, value }) => {\n if (siblingData._status === "published" && !value) {\n return new Date()\n }\n return value\n },\n ],\n },\n },\n {\n name: "authors",\n type: "relationship",\n admin: {\n position: "sidebar",\n },\n hasMany: true,\n relationTo: "users",\n },\n {\n name: "populatedAuthors",\n type: "array",\n access: {\n update: () => false,\n },\n admin: {\n disabled: true,\n readOnly: true,\n },\n fields: [\n {\n name: "id",\n type: "text",\n },\n {\n name: "name",\n type: "text",\n },\n ],\n },\n slugField(),\n ],\n hooks: {\n afterChange: [revalidatePost],\n afterRead: [populateAuthors],\n afterDelete: [revalidateDelete],\n },\n versions: {\n drafts: {\n autosave: {\n interval: 100,\n },\n schedulePublish: true,\n },\n maxPerDoc: 50,\n },\n}\n',
890
+ "marketing/payload/src/collections/Users/index.ts.hbs": 'import type { CollectionConfig } from "payload"\n\nimport { authenticated } from "../../access/authenticated"\n\nexport const Users: CollectionConfig = {\n slug: "users",\n access: {\n admin: authenticated,\n create: authenticated,\n delete: authenticated,\n read: authenticated,\n update: authenticated,\n },\n admin: {\n defaultColumns: ["name", "email"],\n useAsTitle: "name",\n },\n auth: true,\n fields: [\n {\n name: "name",\n type: "text",\n },\n ],\n timestamps: true,\n}\n',
891
+ "marketing/payload/src/collections/index.ts.hbs": 'export { Users } from "./Users"\nexport { Media } from "./Media"\nexport { Pages } from "./Pages"\nexport { Posts } from "./Posts"\nexport { Categories } from "./Categories"\nexport { FAQs } from "./FAQs"\n',
892
+ "marketing/payload/src/components/BeforeDashboard/SeedButton/index.scss.hbs": ".seedButton {\n appearance: none;\n background: none;\n border: none;\n padding: 0;\n text-decoration: underline;\n\n &:hover {\n cursor: pointer;\n opacity: 0.85;\n }\n}\n",
893
+ "marketing/payload/src/components/BeforeDashboard/SeedButton/index.tsx.hbs": '"use client"\n\nimport { toast } from "@payloadcms/ui"\nimport type React from "react"\nimport { Fragment, useCallback, useState } from "react"\n\nimport "./index.scss"\n\nconst SuccessMessage: React.FC = () => (\n <div>\n Database seeded! You can now{" "}\n <a target="_blank" href="/" rel="noreferrer">\n visit your website\n </a>\n </div>\n)\n\nexport const SeedButton: React.FC = () => {\n const [loading, setLoading] = useState(false)\n const [seeded, setSeeded] = useState(false)\n const [error, setError] = useState<null | string>(null)\n\n const handleClick = useCallback(\n async (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault()\n\n if (seeded) {\n toast.info("Database already seeded.")\n return\n }\n if (loading) {\n toast.info("Seeding already in progress.")\n return\n }\n if (error) {\n toast.error(`An error occurred, please refresh and try again.`)\n return\n }\n\n setLoading(true)\n\n try {\n toast.promise(\n new Promise((resolve, reject) => {\n try {\n fetch("/next/seed", { method: "POST", credentials: "include" })\n .then((res) => {\n if (res.ok) {\n resolve(true)\n setSeeded(true)\n } else {\n reject("An error occurred while seeding.")\n }\n })\n .catch((error) => {\n reject(error)\n })\n } catch (error) {\n reject(error)\n }\n }),\n {\n loading: "Seeding with data....",\n success: <SuccessMessage />,\n error: "An error occurred while seeding.",\n },\n )\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err)\n setError(error)\n }\n },\n [loading, seeded, error],\n )\n\n let message = ""\n if (loading) message = " (seeding...)"\n if (seeded) message = " (done!)"\n if (error) message = ` (error: ${error})`\n\n return (\n <Fragment>\n <button className="seedButton" onClick={handleClick}>\n Seed your database\n </button>\n {message}\n </Fragment>\n )\n}\n',
894
+ "marketing/payload/src/components/BeforeDashboard/index.scss.hbs": "@import '~@payloadcms/ui/scss';\n\n.dashboard .before-dashboard {\n margin-bottom: base(1.5);\n\n &__banner {\n & h4 {\n margin: 0;\n }\n }\n\n &__instructions {\n list-style: decimal;\n margin-bottom: base(0.5);\n\n & li {\n width: 100%;\n }\n }\n\n & a:hover {\n opacity: 0.85;\n }\n}\n",
895
+ "marketing/payload/src/components/BeforeDashboard/index.tsx.hbs": 'import { Banner } from "@payloadcms/ui/elements/Banner"\nimport type React from "react"\n\nimport { SeedButton } from "./SeedButton"\nimport "./index.scss"\n\nconst baseClass = "before-dashboard"\n\nconst BeforeDashboard: React.FC = () => {\n return (\n <div className={baseClass}>\n <Banner className={`${baseClass}__banner`} type="success">\n <h4>Welcome to your dashboard!</h4>\n </Banner>\n Here&apos;s what to do next:\n <ul className={`${baseClass}__instructions`}>\n <li>\n <SeedButton />\n {" with a few pages and posts to jump-start your new site, then "}\n <a href="/" target="_blank" rel="noreferrer">\n visit your website\n </a>\n {" to see the results."}\n </li>\n <li>\n {"Modify your "}\n <a\n href="https://payloadcms.com/docs/configuration/collections"\n rel="noopener noreferrer"\n target="_blank"\n >\n collections\n </a>\n {" and add more "}\n <a\n href="https://payloadcms.com/docs/fields/overview"\n rel="noopener noreferrer"\n target="_blank"\n >\n fields\n </a>\n {" as needed. If you are new to Payload, we also recommend you check out the "}\n <a\n href="https://payloadcms.com/docs/getting-started/what-is-payload"\n rel="noopener noreferrer"\n target="_blank"\n >\n Getting Started\n </a>\n {" docs."}\n </li>\n <li>\n Commit and push your changes to the repository to trigger a redeployment of your project.\n </li>\n </ul>\n {"Pro Tip: This block is a "}\n <a\n href="https://payloadcms.com/docs/custom-components/overview"\n rel="noopener noreferrer"\n target="_blank"\n >\n custom component\n </a>\n , you can remove it at any time by updating your <strong>payload.config</strong>.\n </div>\n )\n}\n\nexport default BeforeDashboard\n',
896
+ "marketing/payload/src/components/BeforeLogin/index.tsx.hbs": 'import type React from "react"\n\nconst BeforeLogin: React.FC = () => {\n return (\n <div>\n <p>\n <b>Welcome to your dashboard!</b>\n {" This is where site admins will log in to manage your website."}\n </p>\n </div>\n )\n}\n\nexport default BeforeLogin\n',
897
+ "marketing/payload/src/components/Link/index.tsx.hbs": 'import { cn } from "@/lib/utils"\nimport Link from "next/link"\nimport type React from "react"\n\nimport type { Page, Post } from "@/payload-types"\n\ntype CMSLinkType = {\n appearance?: "inline" | "default" | "outline" | "link"\n children?: React.ReactNode\n className?: string\n label?: string | null\n newTab?: boolean | null\n reference?: {\n relationTo: "pages" | "posts"\n value: Page | Post | string | number\n } | null\n size?: "default" | "sm" | "lg" | null\n type?: "custom" | "reference" | null\n url?: string | null\n}\n\nexport const CMSLink: React.FC<CMSLinkType> = (props) => {\n const {\n type,\n appearance = "inline",\n children,\n className,\n label,\n newTab,\n reference,\n size = "default",\n url,\n } = props\n\n const href =\n type === "reference" && typeof reference?.value === "object" && reference.value.slug\n ? `${reference?.relationTo !== "pages" ? `/${reference?.relationTo}` : ""}/${\n reference.value.slug\n }`\n : url\n\n if (!href) return null\n\n const newTabProps = newTab ? { rel: "noopener noreferrer", target: "_blank" } : {}\n\n // Size classes\n const sizeClasses = {\n default: "px-4 py-2",\n sm: "px-3 py-1 text-sm",\n lg: "px-6 py-3 text-lg",\n }\n\n // Appearance classes\n const appearanceClasses = {\n inline: "",\n default: cn(\n "inline-flex items-center justify-center rounded-md font-medium transition-colors",\n "bg-primary text-primary-foreground hover:bg-primary/90",\n sizeClasses[size || "default"]\n ),\n outline: cn(\n "inline-flex items-center justify-center rounded-md font-medium transition-colors",\n "border border-input bg-background hover:bg-accent hover:text-accent-foreground",\n sizeClasses[size || "default"]\n ),\n link: "underline-offset-4 hover:underline",\n }\n\n return (\n <Link\n className={cn(appearanceClasses[appearance], className)}\n href={href || url || ""}\n {...newTabProps}\n >\n {label && label}\n {children && children}\n </Link>\n )\n}\n',
898
+ "marketing/payload/src/components/Media/index.tsx.hbs": '"use client"\n\nimport { cn } from "@/lib/utils"\nimport Image from "next/image"\nimport type React from "react"\n\nimport type { Media as MediaType } from "@/payload-types"\n\nexport interface MediaProps {\n resource?: MediaType | string | number | null\n alt?: string\n className?: string\n imgClassName?: string\n fill?: boolean\n priority?: boolean\n size?: string\n}\n\nexport const Media: React.FC<MediaProps> = ({\n resource,\n alt: altFromProps,\n className,\n imgClassName,\n fill = false,\n priority = false,\n size,\n}) => {\n // If resource is not an object or is null/undefined, return null\n if (!resource || typeof resource !== "object") {\n return null\n }\n\n const { url, alt: altFromResource, width, height } = resource\n\n const alt = altFromProps ?? altFromResource ?? ""\n\n if (!url) return null\n\n // Handle fill mode\n if (fill) {\n return (\n <div className={cn("relative", className)}>\n <Image\n src={url}\n alt={alt}\n fill\n className={cn("object-cover", imgClassName)}\n priority={priority}\n sizes={size || "100vw"}\n />\n </div>\n )\n }\n\n // Handle normal mode with width/height\n return (\n <Image\n src={url}\n alt={alt}\n width={width || 800}\n height={height || 600}\n className={cn(className, imgClassName)}\n priority={priority}\n sizes={size}\n />\n )\n}\n',
899
+ "marketing/payload/src/components/RichText/index.tsx.hbs": 'import type { DefaultTypedEditorState } from "@payloadcms/richtext-lexical"\nimport {\n RichText as ConvertRichText,\n type JSXConvertersFunction,\n LinkJSXConverter,\n} from "@payloadcms/richtext-lexical/react"\nimport { cn } from "@/lib/utils"\nimport type React from "react"\n\nconst jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => ({\n ...defaultConverters,\n ...LinkJSXConverter({ internalDocToHref: ({ linkNode }) => {\n const { value, relationTo } = linkNode.fields.doc || {}\n if (typeof value !== "object" || !value) return "/"\n const slug = value.slug\n return relationTo === "posts" ? `/posts/${slug}` : `/${slug}`\n }}),\n})\n\ntype Props = {\n data: DefaultTypedEditorState\n enableGutter?: boolean\n enableProse?: boolean\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport default function RichText(props: Props) {\n const { className, enableProse = true, enableGutter = true, ...rest } = props\n return (\n <ConvertRichText\n converters={jsxConverters}\n className={cn(\n "payload-richtext",\n {\n container: enableGutter,\n "prose prose-lg dark:prose-invert prose-headings:font-bold prose-headings:tracking-tight prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-blockquote:border-l-primary prose-blockquote:not-italic prose-li:marker:text-muted-foreground":\n enableProse,\n },\n !enableGutter && "max-w-none",\n className,\n )}\n {...rest}\n />\n )\n}\n',
900
+ "marketing/payload/src/endpoints/seed/home.ts.hbs": 'import type { Media } from "@/payload-types"\nimport type { RequiredDataFromCollectionSlug } from "payload"\n\ntype HomeArgs = {\n heroImage: Media\n}\n\nexport const home: (args: HomeArgs) => RequiredDataFromCollectionSlug<"pages"> = ({\n heroImage,\n}) => {\n return {\n slug: "home",\n _status: "published",\n title: "Home",\n layout: [\n {\n blockType: "hero",\n heading: "Welcome to {{projectName}}",\n subheading: "Build something amazing with Payload CMS and Next.js",\n primaryCta: {\n label: "Get Started",\n url: "/posts",\n },\n secondaryCta: {\n label: "Learn More",\n url: "/contact",\n },\n },\n {\n blockType: "features",\n heading: "Core Features",\n subheading: "Everything you need to build modern websites",\n features: [\n {\n icon: "layout",\n title: "Page Builder",\n description: "Create beautiful pages with our flexible block-based editor.",\n },\n {\n icon: "zap",\n title: "Lightning Fast",\n description: "Optimized for performance with Next.js and React Server Components.",\n },\n {\n icon: "shield",\n title: "Secure by Default",\n description: "Built-in authentication and role-based access control.",\n },\n {\n icon: "database",\n title: "Flexible Database",\n description: "Works with MongoDB, PostgreSQL, and other databases.",\n },\n ],\n },\n {\n blockType: "cta",\n heading: "Ready to get started?",\n subheading: "Start building your next project today.",\n primaryCta: {\n label: "View Posts",\n url: "/posts",\n },\n secondaryCta: {\n label: "Contact Us",\n url: "/contact",\n },\n },\n ],\n meta: {\n description: "Welcome to {{projectName}} - Built with Payload CMS and Next.js",\n image: heroImage.id,\n title: "{{projectName}}",\n },\n }\n}\n',
901
+ "marketing/payload/src/endpoints/seed/image-1.ts.hbs": 'import type { Media } from "@/payload-types"\n\nexport const image1: Omit<Media, "createdAt" | "id" | "updatedAt"> = {\n alt: "Curving abstract shapes with an orange and blue gradient",\n}\n',
902
+ "marketing/payload/src/endpoints/seed/image-2.ts.hbs": 'import type { Media } from "@/payload-types"\n\nexport const image2: Omit<Media, "createdAt" | "id" | "updatedAt"> = {\n alt: "Stylized 3D rendering of a dark, abstract cosmic landscape",\n}\n',
903
+ "marketing/payload/src/endpoints/seed/image-hero.ts.hbs": 'import type { Media } from "@/payload-types"\n\nexport const imageHero: Omit<Media, "createdAt" | "id" | "updatedAt"> = {\n alt: "Abstract hero image with gradient",\n}\n',
904
+ "marketing/payload/src/endpoints/seed/index.ts.hbs": 'import type { CollectionSlug, File, Payload, PayloadRequest } from "payload"\n\nimport { home } from "./home"\nimport { image1 } from "./image-1"\nimport { image2 } from "./image-2"\nimport { imageHero } from "./image-hero"\nimport { post1 } from "./post-1"\n\nconst collections: CollectionSlug[] = [\n "categories",\n "media",\n "pages",\n "posts",\n]\n\nconst categories = ["Technology", "News", "Finance", "Design", "Software", "Engineering"]\n\n// Next.js revalidation errors are normal when seeding the database without a server running\n// i.e. running `yarn seed` locally instead of using the admin UI within an active app\n// The app is not running to revalidate the pages and so the API routes are not available\n// These error messages can be ignored: `Error hitting revalidate route for...`\nexport const seed = async ({\n payload,\n req,\n}: {\n payload: Payload\n req: PayloadRequest\n}): Promise<void> => {\n payload.logger.info("Seeding database...")\n\n // we need to clear the media directory before seeding\n // as well as the collections and globals\n // this is because while `yarn seed` drops the database\n // the custom `/api/seed` endpoint does not\n payload.logger.info(`\u2014 Clearing collections and globals...`)\n\n // clear the database - header\n await payload.updateGlobal({\n slug: "header",\n data: {\n navItems: [],\n },\n depth: 0,\n context: {\n disableRevalidate: true,\n },\n })\n\n // clear the database - footer\n await payload.updateGlobal({\n slug: "footer",\n data: {\n columns: [],\n socialLinks: {},\n newsletter: { enabled: false },\n copyrightText: "",\n bottomLinks: [],\n },\n depth: 0,\n context: {\n disableRevalidate: true,\n },\n })\n\n await Promise.all(\n collections.map((collection) => payload.db.deleteMany({ collection, req, where: {} })),\n )\n\n await Promise.all(\n collections\n .filter((collection) => Boolean(payload.collections[collection].config.versions))\n .map((collection) => payload.db.deleteVersions({ collection, req, where: {} })),\n )\n\n payload.logger.info(`\u2014 Seeding demo author and user...`)\n\n await payload.delete({\n collection: "users",\n depth: 0,\n where: {\n email: {\n equals: "demo-author@example.com",\n },\n },\n })\n\n payload.logger.info(`\u2014 Seeding media...`)\n\n const [image1Buffer, image2Buffer, heroBuffer] = await Promise.all([\n fetchFileByURL(\n "https://raw.githubusercontent.com/payloadcms/payload/refs/heads/main/templates/website/src/endpoints/seed/image-post1.webp",\n ),\n fetchFileByURL(\n "https://raw.githubusercontent.com/payloadcms/payload/refs/heads/main/templates/website/src/endpoints/seed/image-post2.webp",\n ),\n fetchFileByURL(\n "https://raw.githubusercontent.com/payloadcms/payload/refs/heads/main/templates/website/src/endpoints/seed/image-hero1.webp",\n ),\n ])\n\n const [demoAuthor, image1Doc, image2Doc, imageHeroDoc] = await Promise.all([\n payload.create({\n collection: "users",\n data: {\n name: "Demo Author",\n email: "demo-author@example.com",\n password: "password",\n },\n }),\n payload.create({\n collection: "media",\n data: image1,\n file: image1Buffer,\n }),\n payload.create({\n collection: "media",\n data: image2,\n file: image2Buffer,\n }),\n payload.create({\n collection: "media",\n data: imageHero,\n file: heroBuffer,\n }),\n ...categories.map((category) =>\n payload.create({\n collection: "categories",\n data: {\n title: category,\n },\n }),\n ),\n ])\n\n payload.logger.info(`\u2014 Seeding posts...`)\n\n const post1Doc = await payload.create({\n collection: "posts",\n depth: 0,\n context: {\n disableRevalidate: true,\n },\n data: post1({ heroImage: image1Doc, author: demoAuthor }),\n })\n\n payload.logger.info(`\u2014 Seeding pages...`)\n\n await payload.create({\n collection: "pages",\n depth: 0,\n data: home({ heroImage: imageHeroDoc }),\n })\n\n payload.logger.info(`\u2014 Seeding globals...`)\n\n await Promise.all([\n payload.updateGlobal({\n slug: "header",\n data: {\n navItems: [\n {\n type: "link",\n label: "Posts",\n link: {\n type: "custom",\n url: "/posts",\n },\n },\n ],\n },\n }),\n payload.updateGlobal({\n slug: "footer",\n data: {\n columns: [\n {\n title: "Resources",\n links: [\n {\n link: {\n type: "custom",\n label: "Admin",\n url: "/admin",\n },\n },\n {\n link: {\n type: "custom",\n label: "Payload Docs",\n newTab: true,\n url: "https://payloadcms.com/docs",\n },\n },\n ],\n },\n ],\n socialLinks: {\n github: "https://github.com/payloadcms/payload",\n twitter: "https://x.com/payloadcms",\n },\n newsletter: {\n enabled: true,\n title: "Newsletter",\n description: "Stay up to date with the latest updates.",\n buttonText: "Subscribe",\n placeholder: "Enter your email",\n },\n copyrightText: "{{projectName}}",\n bottomLinks: [],\n },\n }),\n ])\n\n payload.logger.info("Seeded database successfully!")\n}\n\nasync function fetchFileByURL(url: string): Promise<File> {\n const res = await fetch(url, {\n credentials: "include",\n method: "GET",\n })\n\n if (!res.ok) {\n throw new Error(`Failed to fetch file from ${url}, status: ${res.status}`)\n }\n\n const data = await res.arrayBuffer()\n\n return {\n name: url.split("/").pop() || `file-${Date.now()}`,\n data: Buffer.from(data),\n mimetype: `image/${url.split(".").pop()}`,\n size: data.byteLength,\n }\n}\n',
905
+ "marketing/payload/src/endpoints/seed/post-1.ts.hbs": 'import type { Media, User } from "@/payload-types"\nimport type { RequiredDataFromCollectionSlug } from "payload"\n\nexport type PostArgs = {\n heroImage: Media\n author: User\n}\n\nexport const post1: (args: PostArgs) => RequiredDataFromCollectionSlug<"posts"> = ({\n heroImage,\n author,\n}) => {\n return {\n slug: "getting-started",\n _status: "published",\n authors: [author],\n content: {\n root: {\n type: "root",\n children: [\n {\n type: "heading",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Welcome to your new Payload CMS site!",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n tag: "h2",\n version: 1,\n },\n {\n type: "paragraph",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "This is a sample post to help you get started. You can edit this post from the admin dashboard or create new ones.",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n textFormat: 0,\n version: 1,\n },\n {\n type: "heading",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Key Features",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n tag: "h3",\n version: 1,\n },\n {\n type: "paragraph",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Payload CMS provides a powerful and flexible content management system that integrates seamlessly with Next.js. Some key features include:",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n textFormat: 0,\n version: 1,\n },\n {\n type: "list",\n children: [\n {\n type: "listitem",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Fully customizable collections and fields",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n value: 1,\n version: 1,\n },\n {\n type: "listitem",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Built-in authentication and access control",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n value: 2,\n version: 1,\n },\n {\n type: "listitem",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Live preview and draft functionality",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n value: 3,\n version: 1,\n },\n {\n type: "listitem",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "SEO optimization tools",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n value: 4,\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n listType: "bullet",\n start: 1,\n tag: "ul",\n version: 1,\n },\n {\n type: "paragraph",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "Visit the ",\n version: 1,\n },\n {\n type: "link",\n children: [\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: "admin dashboard",\n version: 1,\n },\n ],\n direction: "ltr",\n fields: {\n linkType: "custom",\n newTab: false,\n url: "/admin",\n },\n format: "",\n indent: 0,\n version: 3,\n },\n {\n type: "text",\n detail: 0,\n format: 0,\n mode: "normal",\n style: "",\n text: " to start managing your content.",\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n textFormat: 0,\n version: 1,\n },\n ],\n direction: "ltr",\n format: "",\n indent: 0,\n version: 1,\n },\n },\n heroImage: heroImage.id,\n meta: {\n description: "Learn how to get started with your new Payload CMS site.",\n image: heroImage.id,\n title: "Getting Started with Payload CMS",\n },\n relatedPosts: [],\n title: "Getting Started with Payload CMS",\n }\n}\n',
906
+ "marketing/payload/src/fields/defaultLexical.ts.hbs": 'import {\n AlignFeature,\n BlockquoteFeature,\n BoldFeature,\n ChecklistFeature,\n EXPERIMENTAL_TableFeature,\n IndentFeature,\n InlineCodeFeature,\n ItalicFeature,\n LinkFeature,\n type LinkFields,\n OrderedListFeature,\n ParagraphFeature,\n RelationshipFeature,\n StrikethroughFeature,\n SubscriptFeature,\n SuperscriptFeature,\n UnderlineFeature,\n UnorderedListFeature,\n UploadFeature,\n lexicalEditor,\n} from "@payloadcms/richtext-lexical"\nimport type { TextFieldSingleValidation } from "payload"\n\nexport const defaultLexical = lexicalEditor({\n features: [\n ParagraphFeature(),\n UnderlineFeature(),\n BoldFeature(),\n ItalicFeature(),\n StrikethroughFeature(),\n SubscriptFeature(),\n SuperscriptFeature(),\n InlineCodeFeature(),\n BlockquoteFeature(),\n UnorderedListFeature(),\n OrderedListFeature(),\n ChecklistFeature(),\n AlignFeature(),\n IndentFeature(),\n RelationshipFeature(),\n UploadFeature(),\n EXPERIMENTAL_TableFeature(),\n LinkFeature({\n enabledCollections: ["pages", "posts"],\n fields: ({ defaultFields }) => {\n const defaultFieldsWithoutUrl = defaultFields.filter((field) => {\n if ("name" in field && field.name === "url") return false\n return true\n })\n\n return [\n ...defaultFieldsWithoutUrl,\n {\n name: "url",\n type: "text",\n admin: {\n condition: (_data, siblingData) => siblingData?.linkType !== "internal",\n },\n label: ({ t }) => t("fields:enterURL"),\n required: true,\n validate: ((value, options) => {\n if ((options?.siblingData as LinkFields)?.linkType === "internal") {\n return true // no validation needed, as no url should exist for internal links\n }\n return value ? true : "URL is required"\n }) as TextFieldSingleValidation,\n },\n ]\n },\n }),\n ],\n})\n',
907
+ "marketing/payload/src/fields/index.ts.hbs": 'export { link, appearanceOptions, type LinkAppearances } from "./link"\nexport { linkGroup } from "./linkGroup"\nexport { defaultLexical } from "./defaultLexical"\n',
908
+ "marketing/payload/src/fields/link.ts.hbs": 'import type { Field, GroupField } from "payload"\n\nimport deepMerge from "@/utilities/deepMerge"\n\nexport type LinkAppearances = "default" | "outline"\n\nexport const appearanceOptions: Record<LinkAppearances, { label: string; value: string }> = {\n default: {\n label: "Default",\n value: "default",\n },\n outline: {\n label: "Outline",\n value: "outline",\n },\n}\n\ntype LinkType = (options?: {\n appearances?: LinkAppearances[] | false\n disableLabel?: boolean\n overrides?: Partial<GroupField>\n}) => Field\n\nexport const link: LinkType = ({ appearances, disableLabel = false, overrides = {} } = {}) => {\n const linkResult: GroupField = {\n name: "link",\n type: "group",\n admin: {\n hideGutter: true,\n },\n fields: [\n {\n type: "row",\n fields: [\n {\n name: "type",\n type: "radio",\n admin: {\n layout: "horizontal",\n width: "50%",\n },\n defaultValue: "reference",\n options: [\n {\n label: "Internal link",\n value: "reference",\n },\n {\n label: "Custom URL",\n value: "custom",\n },\n ],\n },\n {\n name: "newTab",\n type: "checkbox",\n admin: {\n style: {\n alignSelf: "flex-end",\n },\n width: "50%",\n },\n label: "Open in new tab",\n },\n ],\n },\n ],\n }\n\n const linkTypes: Field[] = [\n {\n name: "reference",\n type: "relationship",\n admin: {\n condition: (_, siblingData) => siblingData?.type === "reference",\n },\n label: "Document to link to",\n relationTo: ["pages", "posts"],\n required: true,\n },\n {\n name: "url",\n type: "text",\n admin: {\n condition: (_, siblingData) => siblingData?.type === "custom",\n },\n label: "Custom URL",\n required: true,\n },\n ]\n\n if (!disableLabel) {\n linkTypes.map((linkType) => ({\n ...linkType,\n admin: {\n ...linkType.admin,\n width: "50%",\n },\n }))\n\n linkResult.fields.push({\n type: "row",\n fields: [\n ...linkTypes,\n {\n name: "label",\n type: "text",\n admin: {\n width: "50%",\n },\n label: "Label",\n required: true,\n },\n ],\n })\n } else {\n linkResult.fields = [...linkResult.fields, ...linkTypes]\n }\n\n if (appearances !== false) {\n let appearanceOptionsToUse = [appearanceOptions.default, appearanceOptions.outline]\n\n if (appearances) {\n appearanceOptionsToUse = appearances.map((appearance) => appearanceOptions[appearance])\n }\n\n linkResult.fields.push({\n name: "appearance",\n type: "select",\n admin: {\n description: "Choose how the link should be rendered.",\n },\n defaultValue: "default",\n options: appearanceOptionsToUse,\n })\n }\n\n return deepMerge(linkResult, overrides)\n}\n',
909
+ "marketing/payload/src/fields/linkGroup.ts.hbs": 'import type { ArrayField, Field } from "payload"\n\nimport type { LinkAppearances } from "./link"\n\nimport deepMerge from "@/utilities/deepMerge"\nimport { link } from "./link"\n\ntype LinkGroupType = (options?: {\n appearances?: LinkAppearances[] | false\n overrides?: Partial<ArrayField>\n}) => Field\n\nexport const linkGroup: LinkGroupType = ({ appearances, overrides = {} } = {}) => {\n const generatedLinkGroup: Field = {\n name: "links",\n type: "array",\n fields: [\n link({\n appearances,\n }),\n ],\n admin: {\n initCollapsed: true,\n },\n }\n\n return deepMerge(generatedLinkGroup, overrides)\n}\n',
910
+ "marketing/payload/src/globals/index.ts.hbs": 'export { Header } from "../Header"\nexport { Footer } from "../Footer"\n',
911
+ "marketing/payload/src/heros/HighImpact/index.tsx.hbs": '"use client"\n\nimport { useHeaderTheme } from "@/providers/HeaderTheme"\nimport type React from "react"\nimport { useEffect } from "react"\n\nimport type { Page } from "@/payload-types"\n\nimport { CMSLink } from "@/components/Link"\nimport { Media } from "@/components/Media"\nimport RichText from "@/components/RichText"\n\nexport const HighImpactHero: React.FC<Page["hero"]> = ({ links, media, richText }) => {\n const { setHeaderTheme } = useHeaderTheme()\n\n useEffect(() => {\n setHeaderTheme("dark")\n })\n\n return (\n <div\n className="relative -mt-[10.4rem] flex items-center justify-center text-white"\n data-theme="dark"\n >\n <div className="container mx-auto px-4 z-10 relative flex items-center justify-center py-32 md:py-40">\n <div className="max-w-4xl text-center">\n {richText && (\n <RichText className="mb-8 prose-headings:text-white prose-p:text-white/90" data={richText} enableGutter={false} enableProse={false} />\n )}\n {Array.isArray(links) && links.length > 0 && (\n <ul className="flex flex-wrap justify-center gap-4">\n {links.map(({ link }, i) => {\n return (\n <li key={i}>\n <CMSLink {...link} size="lg" />\n </li>\n )\n })}\n </ul>\n )}\n </div>\n </div>\n <div className="absolute inset-0 min-h-[80vh] select-none">\n {media && typeof media === "object" && (\n <>\n <Media fill imgClassName="object-cover" priority resource={media} size="100vw" />\n <div className="absolute inset-0 bg-black/60" />\n </>\n )}\n </div>\n </div>\n )\n}\n',
912
+ "marketing/payload/src/heros/LowImpact/index.tsx.hbs": 'import type React from "react"\n\nimport type { Page } from "@/payload-types"\n\nimport { CMSLink } from "@/components/Link"\nimport RichText from "@/components/RichText"\n\ntype LowImpactHeroType =\n | {\n children?: React.ReactNode\n richText?: never\n links?: never\n }\n | (Omit<Page["hero"], "richText"> & {\n children?: never\n richText?: Page["hero"]["richText"]\n })\n\nexport const LowImpactHero: React.FC<LowImpactHeroType> = ({ children, richText, links }) => {\n return (\n <div className="py-20 md:py-32">\n <div className="container mx-auto px-4">\n <div className="text-center max-w-4xl mx-auto">\n {children ||\n (richText && (\n <RichText\n className="mb-8"\n data={richText}\n enableGutter={false}\n enableProse={false}\n />\n ))}\n {Array.isArray(links) && links.length > 0 && (\n <ul className="flex flex-wrap justify-center gap-4">\n {links.map(({ link }, i) => {\n return (\n <li key={i}>\n <CMSLink {...link} size="lg" />\n </li>\n )\n })}\n </ul>\n )}\n </div>\n </div>\n </div>\n )\n}\n',
913
+ "marketing/payload/src/heros/MediumImpact/index.tsx.hbs": '"use client"\n\nimport type React from "react"\n\nimport type { Page } from "@/payload-types"\n\nimport { CMSLink } from "@/components/Link"\nimport { Media } from "@/components/Media"\nimport RichText from "@/components/RichText"\n\nexport const MediumImpactHero: React.FC<Page["hero"]> = ({ links, media, richText }) => {\n return (\n <div className="py-20 md:py-28">\n <div className="container mx-auto px-4">\n <div className="text-center max-w-4xl mx-auto mb-12">\n {richText && (\n <RichText className="mb-8" data={richText} enableGutter={false} enableProse={false} />\n )}\n\n {Array.isArray(links) && links.length > 0 && (\n <ul className="flex flex-wrap justify-center gap-4">\n {links.map(({ link }, i) => {\n return (\n <li key={i}>\n <CMSLink {...link} size="lg" />\n </li>\n )\n })}\n </ul>\n )}\n </div>\n\n {media && typeof media === "object" && (\n <div className="rounded-xl overflow-hidden border border-border shadow-2xl">\n <Media imgClassName="w-full" priority resource={media} />\n {media?.caption && (\n <div className="mt-3 text-center">\n <RichText data={media.caption} enableGutter={false} />\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )\n}\n',
914
+ "marketing/payload/src/heros/PostHero/index.tsx.hbs": 'import type React from "react"\n\nimport type { Post } from "@/payload-types"\n\nimport { formatAuthors } from "@/utilities/formatAuthors"\nimport { formatDateTime } from "@/utilities/formatDateTime"\nimport Link from "next/link"\n\nexport const PostHero: React.FC<{\n post: Post\n}> = ({ post }) => {\n const { categories, populatedAuthors, publishedAt, title } = post\n\n const hasAuthors =\n populatedAuthors && populatedAuthors.length > 0 && formatAuthors(populatedAuthors) !== ""\n\n return (\n <div className="relative bg-gradient-to-b from-muted/50 to-background">\n <div className="container py-16 md:py-20 lg:py-24">\n <div className="max-w-3xl">\n {/* Category Badge */}\n {categories && categories.length > 0 && (\n <div className="flex items-center gap-2 mb-6">\n {categories.map((category) => {\n if (typeof category === "object" && category !== null) {\n const { title: categoryTitle, slug, id } = category\n const titleToUse = categoryTitle || "Untitled category"\n\n return (\n <Link\n key={id || slug}\n href={`/posts?category=${slug}`}\n className="inline-flex items-center px-3 py-1 text-xs font-medium uppercase tracking-wider text-primary bg-primary/10 rounded-full hover:bg-primary/20 transition-colors"\n >\n {titleToUse}\n </Link>\n )\n }\n return null\n })}\n </div>\n )}\n\n {/* Title */}\n <h1 className="text-3xl md:text-4xl lg:text-5xl font-bold leading-tight mb-8">\n {title}\n </h1>\n\n {/* Meta Information */}\n <div className="flex items-center gap-6 text-sm text-muted-foreground">\n {hasAuthors && (\n <div className="flex items-center gap-2">\n <span className="text-muted-foreground/70">By</span>\n <span className="font-medium">{formatAuthors(populatedAuthors)}</span>\n </div>\n )}\n {hasAuthors && publishedAt && <span className="text-muted-foreground/50">\u2022</span>}\n {publishedAt && (\n <time dateTime={publishedAt}>\n {formatDateTime(publishedAt)}\n </time>\n )}\n </div>\n </div>\n </div>\n </div>\n )\n}\n',
915
+ "marketing/payload/src/heros/ProductShowcase/index.tsx.hbs": '"use client"\n\nimport { useHeaderTheme } from "@/providers/HeaderTheme"\nimport type React from "react"\nimport { useEffect } from "react"\n\nimport type { Page } from "@/payload-types"\n\nimport { CMSLink } from "@/components/Link"\nimport { Media } from "@/components/Media"\nimport RichText from "@/components/RichText"\n\nexport const ProductShowcaseHero: React.FC<Page["hero"]> = ({\n links,\n richText,\n media,\n backgroundMedia,\n}) => {\n const { setHeaderTheme } = useHeaderTheme()\n const hasMedia = media && typeof media === "object"\n const hasBackgroundMedia = backgroundMedia && typeof backgroundMedia === "object"\n\n useEffect(() => {\n setHeaderTheme("light")\n }, [setHeaderTheme])\n\n return (\n <div className="relative overflow-hidden">\n {/* Hero Content - Left Aligned */}\n <div className="container mx-auto px-4 pt-8 pb-16 md:pt-16 md:pb-24">\n <div className="max-w-2xl">\n {richText && (\n <RichText\n className="mb-8"\n data={richText}\n enableGutter={false}\n enableProse={false}\n />\n )}\n {Array.isArray(links) && links.length > 0 && (\n <ul className="flex flex-wrap gap-4">\n {links.map(({ link }, i) => {\n return (\n <li key={i}>\n <CMSLink {...link} size="lg" />\n </li>\n )\n })}\n </ul>\n )}\n </div>\n </div>\n\n {/* Product Showcase Section */}\n <div className="container mx-auto px-4">\n <div className="relative rounded-2xl overflow-hidden min-h-[400px] md:min-h-[500px]">\n {/* Background */}\n <div className="absolute inset-0">\n {hasBackgroundMedia ? (\n <Media\n resource={backgroundMedia}\n fill\n imgClassName="object-cover"\n priority\n size="100vw"\n />\n ) : (\n <div className="w-full h-full bg-gradient-to-br from-primary/10 via-primary/5 to-background" />\n )}\n </div>\n\n {/* Product Media - centered */}\n {hasMedia && (\n <div className="relative z-10 flex items-center justify-center p-8 md:p-12">\n <div className="max-w-4xl w-full rounded-lg overflow-hidden shadow-2xl border border-border/50">\n <Media\n resource={media}\n imgClassName="w-full h-auto object-contain"\n size="(max-width: 768px) 100vw, (max-width: 1024px) 80vw, 960px"\n />\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n',
916
+ "marketing/payload/src/heros/RenderHero.tsx.hbs": 'import type React from "react"\n\nimport type { Page } from "@/payload-types"\n\nimport { HighImpactHero } from "@/heros/HighImpact"\nimport { LowImpactHero } from "@/heros/LowImpact"\nimport { MediumImpactHero } from "@/heros/MediumImpact"\nimport { ProductShowcaseHero } from "@/heros/ProductShowcase"\n\nconst heroes = {\n highImpact: HighImpactHero,\n lowImpact: LowImpactHero,\n mediumImpact: MediumImpactHero,\n productShowcase: ProductShowcaseHero,\n}\n\nexport const RenderHero: React.FC<Page["hero"]> = (props) => {\n const { type } = props || {}\n\n if (!type || type === "none") return null\n\n const HeroToRender = heroes[type]\n\n if (!HeroToRender) return null\n\n return <HeroToRender {...props} />\n}\n',
917
+ "marketing/payload/src/heros/config.ts.hbs": 'import type { Field } from "payload"\n\nimport {\n AlignFeature,\n BlockquoteFeature,\n ChecklistFeature,\n FixedToolbarFeature,\n HeadingFeature,\n IndentFeature,\n InlineCodeFeature,\n InlineToolbarFeature,\n OrderedListFeature,\n RelationshipFeature,\n StrikethroughFeature,\n SubscriptFeature,\n SuperscriptFeature,\n UnorderedListFeature,\n UploadFeature,\n lexicalEditor,\n} from "@payloadcms/richtext-lexical"\n\nimport { linkGroup } from "@/fields/linkGroup"\n\nexport const hero: Field = {\n name: "hero",\n type: "group",\n fields: [\n {\n name: "type",\n type: "select",\n defaultValue: "lowImpact",\n label: "Type",\n options: [\n {\n label: "None",\n value: "none",\n },\n {\n label: "Product Showcase",\n value: "productShowcase",\n },\n {\n label: "High Impact",\n value: "highImpact",\n },\n {\n label: "Medium Impact",\n value: "mediumImpact",\n },\n {\n label: "Low Impact",\n value: "lowImpact",\n },\n ],\n required: true,\n },\n {\n name: "richText",\n type: "richText",\n editor: lexicalEditor({\n features: ({ rootFeatures }) => {\n return [\n ...rootFeatures,\n HeadingFeature({ enabledHeadingSizes: ["h1", "h2", "h3", "h4"] }),\n FixedToolbarFeature(),\n InlineToolbarFeature(),\n StrikethroughFeature(),\n SubscriptFeature(),\n SuperscriptFeature(),\n InlineCodeFeature(),\n BlockquoteFeature(),\n UnorderedListFeature(),\n OrderedListFeature(),\n ChecklistFeature(),\n AlignFeature(),\n IndentFeature(),\n RelationshipFeature(),\n UploadFeature(),\n ]\n },\n }),\n label: false,\n },\n linkGroup({\n overrides: {\n maxRows: 2,\n },\n }),\n {\n name: "media",\n type: "upload",\n admin: {\n condition: (_, { type } = {}) =>\n ["highImpact", "mediumImpact", "productShowcase"].includes(type),\n },\n relationTo: "media",\n required: false,\n },\n {\n name: "backgroundMedia",\n type: "upload",\n admin: {\n condition: (_, { type } = {}) => type === "productShowcase",\n description: "Optional background illustration. Falls back to gradient if not set.",\n },\n relationTo: "media",\n required: false,\n label: "Background Image",\n },\n ],\n label: false,\n}\n',
918
+ "marketing/payload/src/heros/index.ts.hbs": 'export { hero } from "./config"\nexport { RenderHero } from "./RenderHero"\nexport { HighImpactHero } from "./HighImpact"\nexport { LowImpactHero } from "./LowImpact"\nexport { MediumImpactHero } from "./MediumImpact"\nexport { ProductShowcaseHero } from "./ProductShowcase"\nexport { PostHero } from "./PostHero"\n',
919
+ "marketing/payload/src/hooks/index.ts.hbs": 'export { populatePublishedAt } from "./populatePublishedAt"\nexport { revalidateRedirects } from "./revalidateRedirects"\n',
920
+ "marketing/payload/src/hooks/populatePublishedAt.ts.hbs": 'import type { CollectionBeforeChangeHook } from "payload"\n\nexport const populatePublishedAt: CollectionBeforeChangeHook = ({ data, operation, req }) => {\n if (operation === "create" || operation === "update") {\n if (req.data && !req.data.publishedAt) {\n const now = new Date()\n return {\n ...data,\n publishedAt: now,\n }\n }\n }\n\n return data\n}\n',
921
+ "marketing/payload/src/hooks/revalidateRedirects.ts.hbs": 'import type { CollectionAfterChangeHook } from "payload"\n\nimport { revalidateTag } from "next/cache"\n\nexport const revalidateRedirects: CollectionAfterChangeHook = ({ doc, req: { payload } }) => {\n payload.logger.info(`Revalidating redirects`)\n\n revalidateTag("redirects")\n\n return doc\n}\n',
922
+ "marketing/payload/src/payload.config.ts.hbs": "import path from 'path'\nimport { fileURLToPath } from 'url'\nimport { buildConfig } from 'payload'\nimport { postgresAdapter } from '@payloadcms/db-postgres'\nimport { lexicalEditor } from '@payloadcms/richtext-lexical'\nimport { seoPlugin } from '@payloadcms/plugin-seo'\nimport { resendAdapter } from '@payloadcms/email-resend'\nimport sharp from 'sharp'\n{{#if (eq integrations.payloadStorage 's3')}}\nimport { s3Storage } from '@payloadcms/storage-s3'\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\nimport { s3Storage } from '@payloadcms/storage-s3'\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\nimport { vercelBlobStorage } from '@payloadcms/storage-vercel-blob'\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\nimport { gcsStorage } from '@payloadcms/storage-gcs'\n{{/if}}\n\nimport { Users, Media, Pages, Posts, Categories, FAQs } from './collections'\nimport { Header, Footer } from './globals'\nimport { getServerSideURL } from './utilities/getURL'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nexport default buildConfig({\n admin: {\n user: Users.slug,\n importMap: {\n baseDir: path.resolve(__dirname),\n },\n components: {\n beforeLogin: ['@/components/BeforeLogin'],\n beforeDashboard: ['@/components/BeforeDashboard'],\n },\n livePreview: {\n breakpoints: [\n {\n label: 'Mobile',\n name: 'mobile',\n width: 375,\n height: 667,\n },\n {\n label: 'Tablet',\n name: 'tablet',\n width: 768,\n height: 1024,\n },\n {\n label: 'Desktop',\n name: 'desktop',\n width: 1440,\n height: 900,\n },\n ],\n },\n },\n db: postgresAdapter({\n pool: {\n connectionString: process.env.DATABASE_URL,\n },\n }),\n editor: lexicalEditor(),\n email: resendAdapter({\n defaultFromAddress: process.env.RESEND_FROM_EMAIL || 'noreply@example.com',\n defaultFromName: '{{projectName}}',\n apiKey: process.env.RESEND_API_KEY || '',\n }),\n collections: [Users, Media, Pages, Posts, Categories, FAQs],\n globals: [Header, Footer],\n plugins: [\n{{#if (eq integrations.payloadStorage 's3')}}\n s3Storage({\n collections: {\n media: true,\n },\n bucket: process.env.S3_BUCKET!,\n config: {\n credentials: {\n accessKeyId: process.env.S3_ACCESS_KEY_ID!,\n secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,\n },\n region: process.env.S3_REGION!,\n endpoint: process.env.S3_ENDPOINT,\n forcePathStyle: true,\n },\n }),\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\n s3Storage({\n collections: {\n media: true,\n },\n bucket: process.env.R2_BUCKET!,\n config: {\n credentials: {\n accessKeyId: process.env.R2_ACCESS_KEY_ID!,\n secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,\n },\n region: 'auto',\n endpoint: process.env.R2_ENDPOINT!,\n forcePathStyle: true,\n },\n }),\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\n vercelBlobStorage({\n collections: {\n media: true,\n },\n token: process.env.BLOB_READ_WRITE_TOKEN!,\n }),\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\n gcsStorage({\n collections: {\n media: true,\n },\n bucket: process.env.GCS_BUCKET!,\n options: {\n projectId: process.env.GCS_PROJECT_ID,\n credentials: JSON.parse(process.env.GCS_CREDENTIALS || '{}'),\n },\n }),\n{{/if}}\n seoPlugin({\n collections: ['pages', 'posts'],\n uploadsCollection: 'media',\n generateTitle: ({ doc }) => `${doc?.title ?? ''} | {{projectName}}`,\n generateDescription: ({ doc }) => doc?.excerpt ?? '',\n }),\n ],\n cors: [getServerSideURL()].filter(Boolean),\n secret: process.env.PAYLOAD_SECRET!,\n sharp,\n typescript: {\n outputFile: path.resolve(__dirname, 'payload-types.ts'),\n },\n{{#if (eq integrations.payloadStorage 'local')}}\n upload: {\n limits: {\n fileSize: 5000000, // 5MB\n },\n },\n{{/if}}\n})\n",
923
+ "marketing/payload/src/providers/HeaderTheme/index.tsx.hbs": '"use client"\n\nimport type { Theme } from "@/providers/Theme/types"\n\nimport type React from "react"\nimport { createContext, use, useCallback, useState } from "react"\n\nimport canUseDOM from "@/utilities/canUseDOM"\n\nexport interface ContextType {\n headerTheme?: Theme | null\n setHeaderTheme: (theme: Theme | null) => void\n}\n\nconst initialContext: ContextType = {\n headerTheme: undefined,\n setHeaderTheme: () => null,\n}\n\nconst HeaderThemeContext = createContext(initialContext)\n\nexport const HeaderThemeProvider = ({ children }: { children: React.ReactNode }) => {\n const [headerTheme, setThemeState] = useState<Theme | undefined | null>(\n canUseDOM ? (document.documentElement.getAttribute("data-theme") as Theme) : undefined,\n )\n\n const setHeaderTheme = useCallback((themeToSet: Theme | null) => {\n setThemeState(themeToSet)\n }, [])\n\n return <HeaderThemeContext value=\\{{ headerTheme, setHeaderTheme }}>{children}</HeaderThemeContext>\n}\n\nexport const useHeaderTheme = (): ContextType => use(HeaderThemeContext)\n',
924
+ "marketing/payload/src/providers/Theme/InitTheme/index.tsx.hbs": `import Script from "next/script"
925
+ import type React from "react"
926
+
927
+ import { defaultTheme, themeLocalStorageKey } from "../shared"
928
+
929
+ export const InitTheme: React.FC = () => {
930
+ return (
931
+ <Script
932
+ dangerouslySetInnerHTML=\\{{
933
+ __html: \`
934
+ (function () {
935
+ function getSystemPreference() {
936
+ var mediaQuery = '(prefers-color-scheme: dark)'
937
+ var mql = window.matchMedia(mediaQuery)
938
+ var hasPreference = typeof mql.matches === 'boolean'
939
+
940
+ if (hasPreference) {
941
+ return mql.matches ? 'dark' : 'light'
942
+ }
943
+
944
+ return '\${defaultTheme}'
945
+ }
946
+
947
+ var themeToSet = '\${defaultTheme}'
948
+ var preference = window.localStorage.getItem('\${themeLocalStorageKey}')
949
+
950
+ if (preference === 'light' || preference === 'dark') {
951
+ // User explicitly chose light or dark
952
+ themeToSet = preference
953
+ } else if (preference === 'auto') {
954
+ // User explicitly chose system preference
955
+ themeToSet = getSystemPreference()
956
+ }
957
+ // If no preference saved, use defaultTheme (light)
958
+
959
+ document.documentElement.setAttribute('data-theme', themeToSet)
960
+ })();
961
+ \`,
962
+ }}
963
+ id="theme-script"
964
+ strategy="beforeInteractive"
965
+ />
966
+ )
967
+ }
968
+ `,
969
+ "marketing/payload/src/providers/Theme/index.tsx.hbs": `"use client"
970
+
971
+ import type React from "react"
972
+ import { createContext, use, useCallback, useEffect, useState } from "react"
973
+
974
+ import type { Theme, ThemeContextType } from "./types"
975
+
976
+ import canUseDOM from "@/utilities/canUseDOM"
977
+ import { defaultTheme, getImplicitPreference, themeLocalStorageKey } from "./shared"
978
+ import { themeIsValid } from "./types"
979
+
980
+ const initialContext: ThemeContextType = {
981
+ setTheme: () => null,
982
+ theme: undefined,
983
+ }
984
+
985
+ const ThemeContext = createContext(initialContext)
986
+
987
+ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
988
+ const [theme, setThemeState] = useState<Theme | undefined>(
989
+ canUseDOM ? (document.documentElement.getAttribute("data-theme") as Theme) : undefined,
990
+ )
991
+
992
+ const setTheme = useCallback((themeToSet: Theme | null) => {
993
+ if (themeToSet === null) {
994
+ // 'auto' mode - use system preference
995
+ const implicitPreference = getImplicitPreference()
996
+ const resolvedTheme = implicitPreference || defaultTheme
997
+ document.documentElement.setAttribute("data-theme", resolvedTheme)
998
+ setThemeState(resolvedTheme)
999
+ } else {
1000
+ setThemeState(themeToSet)
1001
+ document.documentElement.setAttribute("data-theme", themeToSet)
1002
+ }
1003
+ }, [])
1004
+
1005
+ useEffect(() => {
1006
+ let themeToSet: Theme = defaultTheme
1007
+ const preference = window.localStorage.getItem(themeLocalStorageKey)
1008
+
1009
+ if (themeIsValid(preference)) {
1010
+ // User explicitly chose light or dark
1011
+ themeToSet = preference
1012
+ } else if (preference === "auto") {
1013
+ // User explicitly chose system preference
1014
+ const implicitPreference = getImplicitPreference()
1015
+ if (implicitPreference) {
1016
+ themeToSet = implicitPreference
1017
+ }
1018
+ }
1019
+ // If no preference, use defaultTheme (light)
1020
+
1021
+ document.documentElement.setAttribute("data-theme", themeToSet)
1022
+ setThemeState(themeToSet)
1023
+ }, [])
1024
+
1025
+ return <ThemeContext value=\\{{ setTheme, theme }}>{children}</ThemeContext>
1026
+ }
1027
+
1028
+ export const useTheme = (): ThemeContextType => use(ThemeContext)
1029
+ `,
1030
+ "marketing/payload/src/providers/Theme/shared.ts.hbs": 'import type { Theme } from "./types"\n\nexport const themeLocalStorageKey = "payload-theme"\n\nexport const defaultTheme = "light"\n\nexport const getImplicitPreference = (): Theme | null => {\n const mediaQuery = "(prefers-color-scheme: dark)"\n const mql = window.matchMedia(mediaQuery)\n const hasImplicitPreference = typeof mql.matches === "boolean"\n\n if (hasImplicitPreference) {\n return mql.matches ? "dark" : "light"\n }\n\n return null\n}\n',
1031
+ "marketing/payload/src/providers/Theme/types.ts.hbs": 'export type Theme = "dark" | "light"\n\nexport interface ThemeContextType {\n setTheme: (theme: Theme | null) => void\n theme?: Theme | null\n}\n\nexport function themeIsValid(string: null | string): string is Theme {\n return string ? ["dark", "light"].includes(string) : false\n}\n',
1032
+ "marketing/payload/src/providers/index.tsx.hbs": '"use client"\n\nimport type React from "react"\n\nimport { HeaderThemeProvider } from "./HeaderTheme"\nimport { ThemeProvider } from "./Theme"\n\nexport const Providers: React.FC<{\n children: React.ReactNode\n}> = ({ children }) => {\n return (\n <ThemeProvider>\n <HeaderThemeProvider>\n {children}\n </HeaderThemeProvider>\n </ThemeProvider>\n )\n}\n',
1033
+ "marketing/payload/src/utilities/canUseDOM.ts.hbs": 'export default !!(typeof window !== "undefined" && window.document && window.document.createElement)\n',
1034
+ "marketing/payload/src/utilities/deepMerge.ts.hbs": '// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\n\n/**\n * Simple object check.\n * @param item\n * @returns {boolean}\n */\nexport function isObject(item: unknown): item is object {\n return typeof item === "object" && !Array.isArray(item)\n}\n\n/**\n * Deep merge two objects.\n * @param target\n * @param ...sources\n */\nexport default function deepMerge<T, R>(target: T, source: R): T {\n const output = { ...target }\n if (isObject(target) && isObject(source)) {\n Object.keys(source).forEach((key) => {\n if (isObject(source[key])) {\n if (!(key in target)) {\n Object.assign(output, { [key]: source[key] })\n } else {\n output[key] = deepMerge(target[key], source[key])\n }\n } else {\n Object.assign(output, { [key]: source[key] })\n }\n })\n }\n\n return output\n}\n',
1035
+ "marketing/payload/src/utilities/formatAuthors.ts.hbs": 'import type { Post } from "@/payload-types"\n\n/**\n * Formats an array of populatedAuthors from Posts into a prettified string.\n * @param authors - The populatedAuthors array from a Post.\n * @returns A prettified string of authors.\n * @example\n *\n * [Author1, Author2] becomes \'Author1 and Author2\'\n * [Author1, Author2, Author3] becomes \'Author1, Author2, and Author3\'\n *\n */\nexport const formatAuthors = (\n authors: NonNullable<NonNullable<Post["populatedAuthors"]>[number]>[],\n) => {\n // Ensure we don\'t have any authors without a name\n const authorNames = authors.map((author) => author.name).filter(Boolean)\n\n if (authorNames.length === 0) return ""\n if (authorNames.length === 1) return authorNames[0]\n if (authorNames.length === 2) return `${authorNames[0]} and ${authorNames[1]}`\n\n return `${authorNames.slice(0, -1).join(", ")} and ${authorNames[authorNames.length - 1]}`\n}\n',
1036
+ "marketing/payload/src/utilities/formatDateTime.ts.hbs": "export const formatDateTime = (timestamp: string): string => {\n const now = new Date()\n let date = now\n if (timestamp) date = new Date(timestamp)\n const months = date.getMonth()\n const days = date.getDate()\n\n const MM = months + 1 < 10 ? `0${months + 1}` : months + 1\n const DD = days < 10 ? `0${days}` : days\n const YYYY = date.getFullYear()\n\n return `${MM}/${DD}/${YYYY}`\n}\n",
1037
+ "marketing/payload/src/utilities/generateMeta.ts.hbs": 'import type { Metadata } from "next"\n\nimport type { Config, Media, Page, Post } from "../payload-types"\n\nimport { getServerSideURL } from "./getURL"\nimport { mergeOpenGraph } from "./mergeOpenGraph"\n\nconst getImageURL = (image?: Media | Config["db"]["defaultIDType"] | null) => {\n const serverUrl = getServerSideURL()\n\n let url = `${serverUrl}/og-image.png`\n\n if (image && typeof image === "object" && "url" in image) {\n const ogUrl = image.sizes?.og?.url\n\n url = ogUrl ? `${serverUrl}${ogUrl}` : `${serverUrl}${image.url}`\n }\n\n return url\n}\n\n// Default keywords for SEO\nconst defaultKeywords = [\n "{{projectName}}",\n "website",\n "Next.js",\n "Payload CMS",\n]\n\nexport const generateMeta = async (args: {\n doc: Partial<Page> | Partial<Post> | null\n}): Promise<Metadata> => {\n const { doc } = args\n const serverUrl = getServerSideURL()\n\n const ogImage = getImageURL(doc?.meta?.image)\n\n const title = doc?.meta?.title\n ? `${doc?.meta?.title} | {{projectName}}`\n : "{{projectName}}"\n\n const description =\n doc?.meta?.description ||\n "Welcome to {{projectName}}. Built with Payload CMS and Next.js."\n\n // Generate canonical URL\n const slug = Array.isArray(doc?.slug) ? doc?.slug.join("/") : doc?.slug || ""\n const canonicalUrl = slug === "home" ? serverUrl : `${serverUrl}/${slug}`\n\n return {\n title,\n description,\n keywords: defaultKeywords,\n authors: [{ name: "{{projectName}}", url: serverUrl }],\n creator: "{{projectName}}",\n publisher: "{{projectName}}",\n robots: {\n index: true,\n follow: true,\n googleBot: {\n index: true,\n follow: true,\n "max-video-preview": -1,\n "max-image-preview": "large",\n "max-snippet": -1,\n },\n },\n alternates: {\n canonical: canonicalUrl,\n },\n openGraph: mergeOpenGraph({\n description,\n images: ogImage\n ? [\n {\n url: ogImage,\n width: 1200,\n height: 630,\n alt: title,\n },\n ]\n : undefined,\n title,\n url: canonicalUrl,\n }),\n }\n}\n',
1038
+ "marketing/payload/src/utilities/generatePreviewPath.ts.hbs": 'import type { CollectionSlug, PayloadRequest } from "payload"\n\nconst collectionPrefixMap: Partial<Record<CollectionSlug, string>> = {\n posts: "/posts",\n pages: "",\n}\n\ntype Props = {\n collection: keyof typeof collectionPrefixMap\n slug: string\n req: PayloadRequest\n}\n\nexport const generatePreviewPath = ({ collection, slug }: Props) => {\n // Allow empty strings, e.g. for the homepage\n if (slug === undefined || slug === null) {\n return null\n }\n\n // Encode to support slugs with special characters\n const encodedSlug = encodeURIComponent(slug)\n\n const encodedParams = new URLSearchParams({\n slug: encodedSlug,\n collection,\n path: `${collectionPrefixMap[collection]}/${encodedSlug}`,\n previewSecret: process.env.PREVIEW_SECRET || "",\n })\n\n const url = `/next/preview?${encodedParams.toString()}`\n\n return url\n}\n',
1039
+ "marketing/payload/src/utilities/getURL.ts.hbs": 'import canUseDOM from "./canUseDOM"\n\nexport const getServerSideURL = () => {\n return (\n process.env.NEXT_PUBLIC_SERVER_URL ||\n (process.env.VERCEL_PROJECT_PRODUCTION_URL\n ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`\n : "http://localhost:3000")\n )\n}\n\nexport const getClientSideURL = () => {\n if (canUseDOM) {\n const protocol = window.location.protocol\n const domain = window.location.hostname\n const port = window.location.port\n\n return `${protocol}//${domain}${port ? `:${port}` : ""}`\n }\n\n if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {\n return `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`\n }\n\n return process.env.NEXT_PUBLIC_SERVER_URL || ""\n}\n',
1040
+ "marketing/payload/src/utilities/index.ts.hbs": 'export { default as deepMerge, isObject } from "./deepMerge"\nexport { default as canUseDOM } from "./canUseDOM"\nexport { getServerSideURL, getClientSideURL } from "./getURL"\nexport { generatePreviewPath } from "./generatePreviewPath"\nexport { mergeOpenGraph } from "./mergeOpenGraph"\nexport { generateMeta } from "./generateMeta"\nexport { formatAuthors } from "./formatAuthors"\nexport { formatDateTime } from "./formatDateTime"\n',
1041
+ "marketing/payload/src/utilities/mergeOpenGraph.ts.hbs": 'import type { Metadata } from "next"\nimport { getServerSideURL } from "./getURL"\n\nconst defaultOpenGraph: Metadata["openGraph"] = {\n type: "website",\n description:\n "Welcome to {{projectName}}. Built with Payload CMS and Next.js.",\n images: [\n {\n url: `${getServerSideURL()}/og-image.png`,\n width: 1200,\n height: 630,\n alt: "{{projectName}}",\n },\n ],\n siteName: "{{projectName}}",\n title: "{{projectName}}",\n}\n\nexport const mergeOpenGraph = (og?: Metadata["openGraph"]): Metadata["openGraph"] => {\n return {\n ...defaultOpenGraph,\n ...og,\n images: og?.images ? og.images : defaultOpenGraph.images,\n }\n}\n',
1042
+ "marketing/payload/tsconfig.json.hbs": '{\n "compilerOptions": {\n "target": "ES2017",\n "lib": ["dom", "dom.iterable", "esnext"],\n "allowJs": true,\n "skipLibCheck": true,\n "strict": true,\n "noEmit": true,\n "esModuleInterop": true,\n "module": "esnext",\n "moduleResolution": "bundler",\n "resolveJsonModule": true,\n "isolatedModules": true,\n "jsx": "preserve",\n "incremental": true,\n "plugins": [{ "name": "next" }],\n "paths": {\n "@payload-config": ["./src/payload.config.ts"],\n "@/*": ["./src/*"]\n }\n },\n "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],\n "exclude": ["node_modules"]\n}\n',
716
1043
  "monorepo/package.json.hbs": '{\n "name": "{{projectName}}",\n "version": "0.1.0",\n "private": true,\n "scripts": {\n "dev": "node scripts/dev.mjs",\n "dev:all": "turbo dev",\n "dev:web": "turbo -F @repo/web dev",\n "dev:backend": "turbo -F @repo/backend dev",\n "dev:setup": "pnpm --filter @repo/backend dev:setup",\n "build": "turbo build",\n "lint": "turbo lint",\n "lint:fix": "turbo lint:fix",\n "format": "turbo format",\n "typecheck": "turbo typecheck",\n "test": "turbo test",\n "test:e2e": "turbo test:e2e",\n "clean": "turbo clean && rm -rf node_modules",\n "prepare": "husky"\n },\n "devDependencies": {\n "turbo": "^2.0.0",\n "husky": "^9.0.0",\n "lint-staged": "^15.0.0"\n },\n "packageManager": "pnpm@9.0.0",\n "lint-staged": {\n "*.{js,ts,jsx,tsx}": ["biome check --apply"],\n "*.{json,md}": ["biome format --write"]\n }\n}\n',
717
1044
  "monorepo/pnpm-workspace.yaml.hbs": 'packages:\n - "apps/*"\n - "packages/*"\n',
718
1045
  "monorepo/turbo.json.hbs": '{\n "$schema": "https://turbo.build/schema.json",\n "ui": "tui",\n "tasks": {\n "build": {\n "dependsOn": ["^build"],\n "inputs": ["$TURBO_DEFAULT$", ".env*"],\n "outputs": [".next/**", "!.next/cache/**", "dist/**"]\n },\n "lint": {\n "dependsOn": ["^lint"],\n "inputs": ["$TURBO_DEFAULT$"]\n },\n "lint:fix": {\n "dependsOn": ["^lint:fix"],\n "inputs": ["$TURBO_DEFAULT$"]\n },\n "format": {\n "dependsOn": ["^format"],\n "inputs": ["$TURBO_DEFAULT$"]\n },\n "typecheck": {\n "dependsOn": ["^typecheck"],\n "inputs": ["$TURBO_DEFAULT$"]\n },\n "dev": {\n "cache": false,\n "persistent": true\n },\n "dev:setup": {\n "cache": false,\n "interactive": true\n },\n "test": {\n "dependsOn": ["^build"],\n "inputs": ["$TURBO_DEFAULT$"]\n },\n "test:e2e": {\n "dependsOn": ["build"],\n "inputs": ["$TURBO_DEFAULT$"]\n },\n "clean": {\n "cache": false\n }\n }\n}\n',