kofi-stack-template-generator 2.1.41 → 2.1.43

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.
@@ -1,20 +1,20 @@
1
1
 
2
- > kofi-stack-template-generator@2.1.41 build /Users/theodenanyoh/Documents/Krumalabs/create-kofi-stack-v2/packages/template-generator
2
+ > kofi-stack-template-generator@2.1.43 build /Users/theodenanyoh/Documents/Krumalabs/create-kofi-stack-v2/packages/template-generator
3
3
  > pnpm run prebuild && tsup src/index.ts --format esm --dts
4
4
 
5
5
 
6
- > kofi-stack-template-generator@2.1.41 prebuild /Users/theodenanyoh/Documents/Krumalabs/create-kofi-stack-v2/packages/template-generator
6
+ > kofi-stack-template-generator@2.1.43 prebuild /Users/theodenanyoh/Documents/Krumalabs/create-kofi-stack-v2/packages/template-generator
7
7
  > node scripts/generate-templates.js
8
8
 
9
9
  Generating templates.generated.ts...
10
- Generated templates.generated.ts with 338 templates
10
+ Generated templates.generated.ts with 339 templates
11
11
  CLI Building entry: src/index.ts
12
12
  CLI Using tsconfig: tsconfig.json
13
13
  CLI tsup v8.5.1
14
14
  CLI Target: es2022
15
15
  ESM Build start
16
16
  ESM dist/index.js 2.28 MB
17
- ESM ⚡️ Build success in 56ms
17
+ ESM ⚡️ Build success in 55ms
18
18
  DTS Build start
19
- DTS ⚡️ Build success in 538ms
19
+ DTS ⚡️ Build success in 499ms
20
20
  DTS dist/index.d.ts 2.96 KB
package/dist/index.js CHANGED
@@ -1415,7 +1415,7 @@ GCS_CREDENTIALS="{}" # JSON service account key
1415
1415
  `,
1416
1416
  "marketing/payload/_env.local.hbs": "# Database (Supabase PostgreSQL)\nDATABASE_URL=\n\n# Payload CMS\nPAYLOAD_SECRET=\n\n# Scheduled Jobs\nCRON_SECRET=\n\n# Draft Previews\nPREVIEW_SECRET=\n\n# Email (Resend)\nRESEND_API_KEY=\nRESEND_FROM_EMAIL=\n\n{{#if (eq integrations.payloadStorage 's3')}}\n# S3 Storage\nS3_BUCKET=media\nS3_ACCESS_KEY_ID=\nS3_SECRET_ACCESS_KEY=\nS3_REGION=us-east-1\nS3_ENDPOINT=\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\n# Cloudflare R2 Storage\nR2_BUCKET=\nR2_ACCESS_KEY_ID=\nR2_SECRET_ACCESS_KEY=\nR2_ENDPOINT=\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\n# Vercel Blob Storage\nBLOB_READ_WRITE_TOKEN=\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\n# Google Cloud Storage\nGCS_BUCKET=\nGCS_PROJECT_ID=\nGCS_CREDENTIALS=\n{{/if}}\n",
1417
1417
  "marketing/payload/next.config.ts.hbs": "import { withPayload } from '@payloadcms/next/withPayload'\nimport type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n transpilePackages: ['@repo/ui'],\n}\n\nexport default withPayload(nextConfig)\n",
1418
- "marketing/payload/package.json.hbs": '{\n "name": "@repo/marketing",\n "version": "0.1.0",\n "private": true,\n "type": "module",\n "scripts": {\n "build": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap && next build",\n "dev": "cross-env NODE_OPTIONS=--no-deprecation next dev --port 3000",\n "generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",\n "generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",\n "lint": "biome check .",\n "lint:fix": "biome check --write .",\n "payload": "cross-env NODE_OPTIONS=--no-deprecation payload",\n "start": "cross-env NODE_OPTIONS=--no-deprecation next start",\n "typecheck": "tsc --noEmit",\n "db:push": "payload migrate",\n "db:seed": "tsx src/seed.ts"\n },\n "dependencies": {\n "@payloadcms/admin-bar": "^3.0.0",\n "@payloadcms/db-postgres": "^3.0.0",\n "@payloadcms/email-resend": "^3.0.0",\n "@payloadcms/live-preview-react": "^3.0.0",\n "@payloadcms/next": "^3.0.0",\n "@payloadcms/plugin-form-builder": "^3.0.0",\n "@payloadcms/plugin-nested-docs": "^3.0.0",\n "@payloadcms/plugin-redirects": "^3.0.0",\n "@payloadcms/plugin-search": "^3.0.0",\n "@payloadcms/plugin-seo": "^3.0.0",\n "@payloadcms/richtext-lexical": "^3.0.0",\n "@payloadcms/storage-vercel-blob": "^3.0.0",\n "@payloadcms/ui": "^3.0.0",\n "@radix-ui/react-accordion": "^1.2.0",\n "@radix-ui/react-checkbox": "^1.0.4",\n "@radix-ui/react-label": "^2.0.2",\n "@radix-ui/react-select": "^2.0.0",\n "@radix-ui/react-slot": "^1.0.2",\n "@repo/ui": "workspace:*",\n "class-variance-authority": "^0.7.1",\n "clsx": "^2.1.1",\n "cross-env": "^7.0.3",\n "lucide-react": "^0.562.0",\n "next": "^15.4.10",\n "payload": "^3.70.0",\n "posthog-js": "^1.200.0",\n "prism-react-renderer": "^2.4.1",\n "react": "^19.0.0",\n "react-dom": "^19.0.0",\n "react-hook-form": "^7.71.1",\n "sharp": "^0.34.0",\n "tailwind-merge": "^3.4.0"\n },\n "devDependencies": {\n "@repo/config-typescript": "workspace:*",\n "@tailwindcss/postcss": "^4.0.0",\n "@tailwindcss/typography": "^0.5.19",\n "@types/node": "^20.0.0",\n "@types/react": "^19.0.0",\n "@types/react-dom": "^19.0.0",\n "postcss": "^8.4.0",\n "sass": "^1.86.0",\n "tailwindcss": "^4.0.0",\n "tsx": "^4.0.0",\n "tw-animate-css": "^1.4.0",\n "typescript": "^5.0.0"\n }\n}\n',
1418
+ "marketing/payload/package.json.hbs": '{\n "name": "@repo/marketing",\n "version": "0.1.0",\n "private": true,\n "type": "module",\n "scripts": {\n "build": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap && next build",\n "dev": "cross-env NODE_OPTIONS=--no-deprecation next dev --port 3000",\n "generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",\n "generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",\n "lint": "biome check .",\n "lint:fix": "biome check --write .",\n "payload": "cross-env NODE_OPTIONS=--no-deprecation payload",\n "start": "cross-env NODE_OPTIONS=--no-deprecation next start",\n "typecheck": "tsc --noEmit",\n "db:push": "payload migrate",\n "db:seed": "tsx src/seed.ts"\n },\n "dependencies": {\n "@payloadcms/admin-bar": "^3.0.0",\n "@payloadcms/db-postgres": "^3.0.0",\n "@payloadcms/email-resend": "^3.0.0",\n "@payloadcms/live-preview-react": "^3.0.0",\n "@payloadcms/next": "^3.0.0",\n "@payloadcms/plugin-form-builder": "^3.0.0",\n "@payloadcms/plugin-nested-docs": "^3.0.0",\n "@payloadcms/plugin-redirects": "^3.0.0",\n "@payloadcms/plugin-search": "^3.0.0",\n "@payloadcms/plugin-seo": "^3.0.0",\n "@payloadcms/richtext-lexical": "^3.0.0",\n "@payloadcms/storage-vercel-blob": "^3.0.0",\n "@payloadcms/ui": "^3.0.0",\n "@radix-ui/react-accordion": "^1.2.0",\n "@radix-ui/react-checkbox": "^1.0.4",\n "@radix-ui/react-label": "^2.0.2",\n "@radix-ui/react-select": "^2.0.0",\n "@radix-ui/react-slot": "^1.0.2",\n "@repo/ui": "workspace:*",\n "class-variance-authority": "^0.7.1",\n "clsx": "^2.1.1",\n "cross-env": "^7.0.3",\n "geist": "^1.3.0",\n "lucide-react": "^0.562.0",\n "next": "^15.4.10",\n "payload": "^3.70.0",\n "posthog-js": "^1.200.0",\n "prism-react-renderer": "^2.4.1",\n "react": "^19.0.0",\n "react-dom": "^19.0.0",\n "react-hook-form": "^7.71.1",\n "sharp": "^0.34.0",\n "tailwind-merge": "^3.4.0"\n },\n "devDependencies": {\n "@repo/config-typescript": "workspace:*",\n "@tailwindcss/postcss": "^4.0.0",\n "@tailwindcss/typography": "^0.5.19",\n "@types/node": "^20.0.0",\n "@types/react": "^19.0.0",\n "@types/react-dom": "^19.0.0",\n "postcss": "^8.4.0",\n "sass": "^1.86.0",\n "tailwindcss": "^4.0.0",\n "tsx": "^4.0.0",\n "tw-animate-css": "^1.4.0",\n "typescript": "^5.0.0"\n }\n}\n',
1419
1419
  "marketing/payload/postcss.config.mjs.hbs": "export default {\n plugins: {\n '@tailwindcss/postcss': {},\n },\n}\n",
1420
1420
  "marketing/payload/src/Footer/Component.client.tsx": '"use client"\n\nimport Link from "next/link"\nimport type React from "react"\nimport { useState } from "react"\n\nimport type { Footer, Page, Post } from "@/payload-types"\n\nimport { Logo } from "@/components/Logo/Logo"\nimport { Button } from "@/components/ui/button"\nimport { Input } from "@/components/ui/input"\nimport { ThemeSelector } from "@/providers/Theme/ThemeSelector"\nimport { cn } from "@/utilities/ui"\n\ninterface FooterClientProps {\n data: Footer\n}\n\n// Social icons as inline SVGs for flexibility\nconst SocialIcons = {\n twitter: (\n <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">\n <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />\n </svg>\n ),\n instagram: (\n <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">\n <path\n fillRule="evenodd"\n d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z"\n clipRule="evenodd"\n />\n </svg>\n ),\n linkedin: (\n <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">\n <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />\n </svg>\n ),\n github: (\n <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">\n <path\n fillRule="evenodd"\n d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"\n clipRule="evenodd"\n />\n </svg>\n ),\n youtube: (\n <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">\n <path\n fillRule="evenodd"\n d="M19.812 5.418c.861.23 1.538.907 1.768 1.768C21.998 8.746 22 12 22 12s0 3.255-.418 4.814a2.504 2.504 0 0 1-1.768 1.768c-1.56.419-7.814.419-7.814.419s-6.255 0-7.814-.419a2.505 2.505 0 0 1-1.768-1.768C2 15.255 2 12 2 12s0-3.255.417-4.814a2.507 2.507 0 0 1 1.768-1.768C5.744 5 11.998 5 11.998 5s6.255 0 7.814.418ZM15.194 12 10 15V9l5.194 3Z"\n clipRule="evenodd"\n />\n </svg>\n ),\n}\n\n// Helper function to get URL from link\nfunction getLinkUrl(link: {\n type?: ("reference" | "custom") | null\n reference?:\n | { relationTo: "pages"; value: number | Page }\n | { relationTo: "posts"; value: number | Post }\n | null\n url?: string | null\n}): string {\n if (link.type === "reference" && link.reference) {\n const value = link.reference.value\n if (typeof value === "object" && "slug" in value) {\n const prefix = link.reference.relationTo === "posts" ? "/posts" : ""\n return `${prefix}/${value.slug}`\n }\n }\n return link.url || "#"\n}\n\nexport const FooterClient: React.FC<FooterClientProps> = ({ data }) => {\n const currentYear = new Date().getFullYear()\n const [email, setEmail] = useState("")\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null)\n\n const { columns, socialLinks, newsletter, copyrightText, bottomLinks } = data\n\n const handleNewsletterSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!email || isSubmitting) return\n\n setIsSubmitting(true)\n setMessage(null)\n\n try {\n const response = await fetch("/api/newsletter", {\n method: "POST",\n headers: { "Content-Type": "application/json" },\n body: JSON.stringify({ email }),\n })\n\n const result = await response.json()\n\n if (result.success) {\n setMessage({ type: "success", text: result.message })\n setEmail("")\n } else {\n setMessage({ type: "error", text: result.message })\n }\n } catch {\n setMessage({ type: "error", text: "Something went wrong. Please try again." })\n } finally {\n setIsSubmitting(false)\n }\n }\n\n // Check if any social links are configured\n const hasSocialLinks =\n socialLinks?.twitter ||\n socialLinks?.instagram ||\n socialLinks?.linkedin ||\n socialLinks?.github ||\n socialLinks?.youtube\n\n return (\n <footer className="mt-auto border-t border-border bg-background">\n {/* Main Footer Content */}\n <div className="container mx-auto px-4 py-12 lg:py-16">\n <div className="grid grid-cols-2 gap-8 md:grid-cols-3 lg:grid-cols-6">\n {/* Link Columns */}\n {columns?.map((column) => (\n <div key={column.id || column.title} className="col-span-1">\n <h3 className="mb-4 text-sm font-medium text-foreground">{column.title}</h3>\n <ul className="space-y-3">\n {column.links?.map((linkItem) => (\n <li key={linkItem.id || linkItem.link.label}>\n <Link\n href={getLinkUrl(linkItem.link)}\n className="text-sm text-muted-foreground transition-colors hover:text-foreground"\n {...(linkItem.link.newTab\n ? { target: "_blank", rel: "noopener noreferrer" }\n : {})}\n >\n {linkItem.link.label}\n </Link>\n </li>\n ))}\n </ul>\n </div>\n ))}\n\n {/* Newsletter Column */}\n {newsletter?.enabled && (\n <div className="col-span-2 md:col-span-3 lg:col-span-2">\n <h3 className="mb-4 text-sm font-medium text-foreground">\n {newsletter.title || "Newsletter"}\n </h3>\n <p className="mb-4 text-sm text-muted-foreground">\n {newsletter.description || "Stay up to date with the latest updates."}\n </p>\n <form\n onSubmit={handleNewsletterSubmit}\n className="space-y-3"\n suppressHydrationWarning\n >\n <div className="flex gap-2">\n <Input\n type="email"\n placeholder={newsletter.placeholder || "Enter your email"}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n className="flex-1"\n disabled={isSubmitting}\n required\n suppressHydrationWarning\n />\n <Button type="submit" disabled={isSubmitting} suppressHydrationWarning>\n {isSubmitting ? "..." : newsletter.buttonText || "Subscribe"}\n </Button>\n </div>\n {message && (\n <p\n className={cn(\n "text-sm",\n message.type === "success" ? "text-green-600" : "text-red-600",\n )}\n >\n {message.text}\n </p>\n )}\n </form>\n </div>\n )}\n </div>\n\n {/* Social Links */}\n {hasSocialLinks && (\n <div className="mt-10 flex items-center gap-4 border-t border-border pt-8">\n {socialLinks?.twitter && (\n <a\n href={socialLinks.twitter}\n target="_blank"\n rel="noopener noreferrer"\n className="text-muted-foreground transition-colors hover:text-foreground"\n aria-label="X (Twitter)"\n >\n {SocialIcons.twitter}\n </a>\n )}\n {socialLinks?.instagram && (\n <a\n href={socialLinks.instagram}\n target="_blank"\n rel="noopener noreferrer"\n className="text-muted-foreground transition-colors hover:text-foreground"\n aria-label="Instagram"\n >\n {SocialIcons.instagram}\n </a>\n )}\n {socialLinks?.linkedin && (\n <a\n href={socialLinks.linkedin}\n target="_blank"\n rel="noopener noreferrer"\n className="text-muted-foreground transition-colors hover:text-foreground"\n aria-label="LinkedIn"\n >\n {SocialIcons.linkedin}\n </a>\n )}\n {socialLinks?.github && (\n <a\n href={socialLinks.github}\n target="_blank"\n rel="noopener noreferrer"\n className="text-muted-foreground transition-colors hover:text-foreground"\n aria-label="GitHub"\n >\n {SocialIcons.github}\n </a>\n )}\n {socialLinks?.youtube && (\n <a\n href={socialLinks.youtube}\n target="_blank"\n rel="noopener noreferrer"\n className="text-muted-foreground transition-colors hover:text-foreground"\n aria-label="YouTube"\n >\n {SocialIcons.youtube}\n </a>\n )}\n </div>\n )}\n </div>\n\n {/* Bottom Bar */}\n <div className="border-t border-border">\n <div className="container mx-auto flex flex-col items-center justify-between gap-4 px-4 py-6 sm:flex-row">\n {/* Logo and Copyright */}\n <div className="flex items-center gap-4">\n <Link href="/" className="flex items-center">\n <Logo variant="auto" className="h-6 w-6" />\n </Link>\n <p className="text-sm text-muted-foreground">\n \xA9 {currentYear} {copyrightText || "DirectoryHub"}\n </p>\n </div>\n\n {/* Bottom Links and Theme Selector */}\n <div className="flex items-center gap-6">\n {bottomLinks?.map((linkItem) => (\n <Link\n key={linkItem.id || linkItem.link.label}\n href={getLinkUrl(linkItem.link)}\n className="text-sm text-muted-foreground transition-colors hover:text-foreground"\n {...(linkItem.link.newTab ? { target: "_blank", rel: "noopener noreferrer" } : {})}\n >\n {linkItem.link.label}\n </Link>\n ))}\n <ThemeSelector />\n </div>\n </div>\n </div>\n </footer>\n )\n}\n',
1421
1421
  "marketing/payload/src/Footer/Component.tsx": 'import { getCachedGlobal } from "@/utilities/getGlobals"\n\nimport type { Footer as FooterType } from "@/payload-types"\n\nimport { FooterClient } from "./Component.client"\n\nexport async function Footer() {\n const footerData: FooterType = await getCachedGlobal("footer", 1)()\n\n return <FooterClient data={footerData} />\n}\n',
@@ -3804,6 +3804,7 @@ export const TrustColumns: Block = {
3804
3804
  "marketing/payload/src/components/ui/pagination.tsx": 'import type { ButtonProps } from "@/components/ui/button"\n\nimport { buttonVariants } from "@/components/ui/button"\nimport { cn } from "@/utilities/ui"\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"\nimport type * as React from "react"\n\nconst Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (\n <nav\n aria-label="pagination"\n className={cn("mx-auto flex w-full justify-center", className)}\n role="navigation"\n {...props}\n />\n)\n\nconst PaginationContent: React.FC<\n { ref?: React.Ref<HTMLUListElement> } & React.HTMLAttributes<HTMLUListElement>\n> = ({ className, ref, ...props }) => (\n <ul className={cn("flex flex-row items-center gap-1", className)} ref={ref} {...props} />\n)\n\nconst PaginationItem: React.FC<\n { ref?: React.Ref<HTMLLIElement> } & React.HTMLAttributes<HTMLLIElement>\n> = ({ className, ref, ...props }) => <li className={cn("", className)} ref={ref} {...props} />\n\ntype PaginationLinkProps = {\n isActive?: boolean\n} & Pick<ButtonProps, "size"> &\n React.ComponentProps<"button">\n\nconst PaginationLink = ({ className, isActive, size = "icon", ...props }: PaginationLinkProps) => (\n <button\n aria-current={isActive ? "page" : undefined}\n className={cn(\n buttonVariants({\n size,\n variant: isActive ? "outline" : "ghost",\n }),\n className,\n )}\n {...props}\n />\n)\n\nconst PaginationPrevious = ({\n className,\n ...props\n}: React.ComponentProps<typeof PaginationLink>) => (\n <PaginationLink\n aria-label="Go to previous page"\n className={cn("gap-1 pl-2.5", className)}\n size="default"\n {...props}\n >\n <ChevronLeft className="h-4 w-4" />\n <span>Previous</span>\n </PaginationLink>\n)\n\nconst PaginationNext = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => (\n <PaginationLink\n aria-label="Go to next page"\n className={cn("gap-1 pr-2.5", className)}\n size="default"\n {...props}\n >\n <span>Next</span>\n <ChevronRight className="h-4 w-4" />\n </PaginationLink>\n)\n\nconst PaginationEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => (\n <span\n aria-hidden\n className={cn("flex h-9 w-9 items-center justify-center", className)}\n {...props}\n >\n <MoreHorizontal className="h-4 w-4" />\n <span className="sr-only">More pages</span>\n </span>\n)\n\nexport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n}\n',
3805
3805
  "marketing/payload/src/components/ui/select.tsx": '"use client"\n\nimport { cn } from "@/utilities/ui"\nimport * as SelectPrimitive from "@radix-ui/react-select"\nimport { Check, ChevronDown, ChevronUp } from "lucide-react"\nimport type * as React from "react"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger: React.FC<\n { ref?: React.Ref<HTMLButtonElement> } & React.ComponentProps<typeof SelectPrimitive.Trigger>\n> = ({ children, className, ref, ...props }) => (\n <SelectPrimitive.Trigger\n className={cn(\n "flex h-10 w-full items-center justify-between rounded border border-input bg-background px-3 py-2 text-inherit ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",\n className,\n )}\n ref={ref}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className="h-4 w-4 opacity-50" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n)\n\nconst SelectScrollUpButton: React.FC<\n { ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>\n> = ({ className, ref, ...props }) => (\n <SelectPrimitive.ScrollUpButton\n className={cn("flex cursor-default items-center justify-center py-1", className)}\n ref={ref}\n {...props}\n >\n <ChevronUp className="h-4 w-4" />\n </SelectPrimitive.ScrollUpButton>\n)\n\nconst SelectScrollDownButton: React.FC<\n { ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<\n typeof SelectPrimitive.ScrollDownButton\n >\n> = ({ className, ref, ...props }) => (\n <SelectPrimitive.ScrollDownButton\n className={cn("flex cursor-default items-center justify-center py-1", className)}\n ref={ref}\n {...props}\n >\n <ChevronDown className="h-4 w-4" />\n </SelectPrimitive.ScrollDownButton>\n)\n\nconst SelectContent: React.FC<\n {\n ref?: React.Ref<HTMLDivElement>\n } & React.ComponentProps<typeof SelectPrimitive.Content>\n> = ({ children, className, position = "popper", ref, ...props }) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n className={cn(\n "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded border bg-card text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",\n position === "popper" &&\n "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",\n className,\n )}\n position={position}\n ref={ref}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n "p-1",\n position === "popper" &&\n "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n)\n\nconst SelectLabel: React.FC<\n { ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<typeof SelectPrimitive.Label>\n> = ({ className, ref, ...props }) => (\n <SelectPrimitive.Label\n className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}\n ref={ref}\n {...props}\n />\n)\n\nconst SelectItem: React.FC<\n { ref?: React.Ref<HTMLDivElement>; value: string } & React.ComponentProps<\n typeof SelectPrimitive.Item\n >\n> = ({ children, className, ref, ...props }) => (\n <SelectPrimitive.Item\n className={cn(\n "relative flex w-full cursor-default select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",\n className,\n )}\n ref={ref}\n {...props}\n >\n <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">\n <SelectPrimitive.ItemIndicator>\n <Check className="h-4 w-4" />\n </SelectPrimitive.ItemIndicator>\n </span>\n\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n)\n\nconst SelectSeparator: React.FC<\n { ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<typeof SelectPrimitive.Separator>\n> = ({ className, ref, ...props }) => (\n <SelectPrimitive.Separator\n className={cn("-mx-1 my-1 h-px bg-muted", className)}\n ref={ref}\n {...props}\n />\n)\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\n',
3806
3806
  "marketing/payload/src/components/ui/textarea.tsx": 'import { cn } from "@/utilities/ui"\nimport type * as React from "react"\n\nconst Textarea: React.FC<\n {\n ref?: React.Ref<HTMLTextAreaElement>\n } & React.TextareaHTMLAttributes<HTMLTextAreaElement>\n> = ({ className, ref, ...props }) => {\n return (\n <textarea\n className={cn(\n "flex min-h-[80px] w-full rounded border border-border bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",\n className,\n )}\n ref={ref}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n',
3807
+ "marketing/payload/src/cssVariables.ts": "export const cssVariables = {\n breakpoints: {\n xs: 400,\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n },\n}\n",
3807
3808
  "marketing/payload/src/endpoints/seed/contact-form.ts": `import type { RequiredDataFromCollectionSlug } from "payload"
3808
3809
 
3809
3810
  export const contactForm: RequiredDataFromCollectionSlug<"forms"> = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kofi-stack-template-generator",
3
- "version": "2.1.41",
3
+ "version": "2.1.43",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  "typecheck": "tsc --noEmit"
18
18
  },
19
19
  "dependencies": {
20
- "kofi-stack-types": "^2.1.41",
20
+ "kofi-stack-types": "^2.1.43",
21
21
  "handlebars": "^4.7.8",
22
22
  "memfs": "^4.9.0"
23
23
  },
@@ -1,7 +1,7 @@
1
1
  // Auto-generated file. Do not edit manually.
2
2
  // Run 'pnpm prebuild' to regenerate.
3
- // Generated: 2026-01-19T02:14:34.205Z
4
- // Template count: 338
3
+ // Generated: 2026-01-19T02:33:07.359Z
4
+ // Template count: 339
5
5
 
6
6
  export const EMBEDDED_TEMPLATES: Record<string, string> = {
7
7
  "admin/next.config.ts.hbs": "import type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n transpilePackages: ['@repo/ui', '@repo/backend'],\n}\n\nexport default nextConfig\n",
@@ -51,7 +51,7 @@ export const EMBEDDED_TEMPLATES: Record<string, string> = {
51
51
  "marketing/payload/_env.example.hbs": "# Database (Supabase PostgreSQL)\nDATABASE_URL=\"postgresql://postgres:[PASSWORD]@db.[PROJECT].supabase.co:5432/postgres\"\n\n# Payload CMS\nPAYLOAD_SECRET=\"\" # Generate with: openssl rand -base64 32\n\n# Scheduled Jobs\nCRON_SECRET=\"\" # Generate with: openssl rand -base64 32\n\n# Draft Previews\nPREVIEW_SECRET=\"\" # Generate with: openssl rand -base64 32\n\n# Email (Resend)\nRESEND_API_KEY=\"\"\nRESEND_FROM_EMAIL=\"noreply@yourdomain.com\"\n\n{{#if (eq integrations.payloadStorage 's3')}}\n# S3 Storage\nS3_BUCKET=\"media\"\nS3_ACCESS_KEY_ID=\"\"\nS3_SECRET_ACCESS_KEY=\"\"\nS3_REGION=\"us-east-1\"\nS3_ENDPOINT=\"\" # Optional: For S3-compatible services\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\n# Cloudflare R2 Storage\nR2_BUCKET=\"\"\nR2_ACCESS_KEY_ID=\"\"\nR2_SECRET_ACCESS_KEY=\"\"\nR2_ENDPOINT=\"https://[ACCOUNT_ID].r2.cloudflarestorage.com\"\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\n# Vercel Blob Storage\nBLOB_READ_WRITE_TOKEN=\"\"\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\n# Google Cloud Storage\nGCS_BUCKET=\"\"\nGCS_PROJECT_ID=\"\"\nGCS_CREDENTIALS=\"{}\" # JSON service account key\n{{/if}}\n{{#if (eq integrations.payloadStorage 'local')}}\n# Local Storage\n# Files are stored in the /media directory by default\n# No additional configuration required\n{{/if}}\n",
52
52
  "marketing/payload/_env.local.hbs": "# Database (Supabase PostgreSQL)\nDATABASE_URL=\n\n# Payload CMS\nPAYLOAD_SECRET=\n\n# Scheduled Jobs\nCRON_SECRET=\n\n# Draft Previews\nPREVIEW_SECRET=\n\n# Email (Resend)\nRESEND_API_KEY=\nRESEND_FROM_EMAIL=\n\n{{#if (eq integrations.payloadStorage 's3')}}\n# S3 Storage\nS3_BUCKET=media\nS3_ACCESS_KEY_ID=\nS3_SECRET_ACCESS_KEY=\nS3_REGION=us-east-1\nS3_ENDPOINT=\n{{/if}}\n{{#if (eq integrations.payloadStorage 'r2')}}\n# Cloudflare R2 Storage\nR2_BUCKET=\nR2_ACCESS_KEY_ID=\nR2_SECRET_ACCESS_KEY=\nR2_ENDPOINT=\n{{/if}}\n{{#if (eq integrations.payloadStorage 'vercel-blob')}}\n# Vercel Blob Storage\nBLOB_READ_WRITE_TOKEN=\n{{/if}}\n{{#if (eq integrations.payloadStorage 'gcs')}}\n# Google Cloud Storage\nGCS_BUCKET=\nGCS_PROJECT_ID=\nGCS_CREDENTIALS=\n{{/if}}\n",
53
53
  "marketing/payload/next.config.ts.hbs": "import { withPayload } from '@payloadcms/next/withPayload'\nimport type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n transpilePackages: ['@repo/ui'],\n}\n\nexport default withPayload(nextConfig)\n",
54
- "marketing/payload/package.json.hbs": "{\n \"name\": \"@repo/marketing\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap && next build\",\n \"dev\": \"cross-env NODE_OPTIONS=--no-deprecation next dev --port 3000\",\n \"generate:importmap\": \"cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap\",\n \"generate:types\": \"cross-env NODE_OPTIONS=--no-deprecation payload generate:types\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"payload\": \"cross-env NODE_OPTIONS=--no-deprecation payload\",\n \"start\": \"cross-env NODE_OPTIONS=--no-deprecation next start\",\n \"typecheck\": \"tsc --noEmit\",\n \"db:push\": \"payload migrate\",\n \"db:seed\": \"tsx src/seed.ts\"\n },\n \"dependencies\": {\n \"@payloadcms/admin-bar\": \"^3.0.0\",\n \"@payloadcms/db-postgres\": \"^3.0.0\",\n \"@payloadcms/email-resend\": \"^3.0.0\",\n \"@payloadcms/live-preview-react\": \"^3.0.0\",\n \"@payloadcms/next\": \"^3.0.0\",\n \"@payloadcms/plugin-form-builder\": \"^3.0.0\",\n \"@payloadcms/plugin-nested-docs\": \"^3.0.0\",\n \"@payloadcms/plugin-redirects\": \"^3.0.0\",\n \"@payloadcms/plugin-search\": \"^3.0.0\",\n \"@payloadcms/plugin-seo\": \"^3.0.0\",\n \"@payloadcms/richtext-lexical\": \"^3.0.0\",\n \"@payloadcms/storage-vercel-blob\": \"^3.0.0\",\n \"@payloadcms/ui\": \"^3.0.0\",\n \"@radix-ui/react-accordion\": \"^1.2.0\",\n \"@radix-ui/react-checkbox\": \"^1.0.4\",\n \"@radix-ui/react-label\": \"^2.0.2\",\n \"@radix-ui/react-select\": \"^2.0.0\",\n \"@radix-ui/react-slot\": \"^1.0.2\",\n \"@repo/ui\": \"workspace:*\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cross-env\": \"^7.0.3\",\n \"lucide-react\": \"^0.562.0\",\n \"next\": \"^15.4.10\",\n \"payload\": \"^3.70.0\",\n \"posthog-js\": \"^1.200.0\",\n \"prism-react-renderer\": \"^2.4.1\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"react-hook-form\": \"^7.71.1\",\n \"sharp\": \"^0.34.0\",\n \"tailwind-merge\": \"^3.4.0\"\n },\n \"devDependencies\": {\n \"@repo/config-typescript\": \"workspace:*\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n \"@tailwindcss/typography\": \"^0.5.19\",\n \"@types/node\": \"^20.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n \"postcss\": \"^8.4.0\",\n \"sass\": \"^1.86.0\",\n \"tailwindcss\": \"^4.0.0\",\n \"tsx\": \"^4.0.0\",\n \"tw-animate-css\": \"^1.4.0\",\n \"typescript\": \"^5.0.0\"\n }\n}\n",
54
+ "marketing/payload/package.json.hbs": "{\n \"name\": \"@repo/marketing\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap && next build\",\n \"dev\": \"cross-env NODE_OPTIONS=--no-deprecation next dev --port 3000\",\n \"generate:importmap\": \"cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap\",\n \"generate:types\": \"cross-env NODE_OPTIONS=--no-deprecation payload generate:types\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"payload\": \"cross-env NODE_OPTIONS=--no-deprecation payload\",\n \"start\": \"cross-env NODE_OPTIONS=--no-deprecation next start\",\n \"typecheck\": \"tsc --noEmit\",\n \"db:push\": \"payload migrate\",\n \"db:seed\": \"tsx src/seed.ts\"\n },\n \"dependencies\": {\n \"@payloadcms/admin-bar\": \"^3.0.0\",\n \"@payloadcms/db-postgres\": \"^3.0.0\",\n \"@payloadcms/email-resend\": \"^3.0.0\",\n \"@payloadcms/live-preview-react\": \"^3.0.0\",\n \"@payloadcms/next\": \"^3.0.0\",\n \"@payloadcms/plugin-form-builder\": \"^3.0.0\",\n \"@payloadcms/plugin-nested-docs\": \"^3.0.0\",\n \"@payloadcms/plugin-redirects\": \"^3.0.0\",\n \"@payloadcms/plugin-search\": \"^3.0.0\",\n \"@payloadcms/plugin-seo\": \"^3.0.0\",\n \"@payloadcms/richtext-lexical\": \"^3.0.0\",\n \"@payloadcms/storage-vercel-blob\": \"^3.0.0\",\n \"@payloadcms/ui\": \"^3.0.0\",\n \"@radix-ui/react-accordion\": \"^1.2.0\",\n \"@radix-ui/react-checkbox\": \"^1.0.4\",\n \"@radix-ui/react-label\": \"^2.0.2\",\n \"@radix-ui/react-select\": \"^2.0.0\",\n \"@radix-ui/react-slot\": \"^1.0.2\",\n \"@repo/ui\": \"workspace:*\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cross-env\": \"^7.0.3\",\n \"geist\": \"^1.3.0\",\n \"lucide-react\": \"^0.562.0\",\n \"next\": \"^15.4.10\",\n \"payload\": \"^3.70.0\",\n \"posthog-js\": \"^1.200.0\",\n \"prism-react-renderer\": \"^2.4.1\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"react-hook-form\": \"^7.71.1\",\n \"sharp\": \"^0.34.0\",\n \"tailwind-merge\": \"^3.4.0\"\n },\n \"devDependencies\": {\n \"@repo/config-typescript\": \"workspace:*\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n \"@tailwindcss/typography\": \"^0.5.19\",\n \"@types/node\": \"^20.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n \"postcss\": \"^8.4.0\",\n \"sass\": \"^1.86.0\",\n \"tailwindcss\": \"^4.0.0\",\n \"tsx\": \"^4.0.0\",\n \"tw-animate-css\": \"^1.4.0\",\n \"typescript\": \"^5.0.0\"\n }\n}\n",
55
55
  "marketing/payload/postcss.config.mjs.hbs": "export default {\n plugins: {\n '@tailwindcss/postcss': {},\n },\n}\n",
56
56
  "marketing/payload/src/Footer/Component.client.tsx": "\"use client\"\n\nimport Link from \"next/link\"\nimport type React from \"react\"\nimport { useState } from \"react\"\n\nimport type { Footer, Page, Post } from \"@/payload-types\"\n\nimport { Logo } from \"@/components/Logo/Logo\"\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { ThemeSelector } from \"@/providers/Theme/ThemeSelector\"\nimport { cn } from \"@/utilities/ui\"\n\ninterface FooterClientProps {\n\tdata: Footer\n}\n\n// Social icons as inline SVGs for flexibility\nconst SocialIcons = {\n\ttwitter: (\n\t\t<svg className=\"h-5 w-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n\t\t\t<path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n\t\t</svg>\n\t),\n\tinstagram: (\n\t\t<svg className=\"h-5 w-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t\td=\"M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z\"\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t/>\n\t\t</svg>\n\t),\n\tlinkedin: (\n\t\t<svg className=\"h-5 w-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n\t\t\t<path d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n\t\t</svg>\n\t),\n\tgithub: (\n\t\t<svg className=\"h-5 w-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t\td=\"M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z\"\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t/>\n\t\t</svg>\n\t),\n\tyoutube: (\n\t\t<svg className=\"h-5 w-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t\td=\"M19.812 5.418c.861.23 1.538.907 1.768 1.768C21.998 8.746 22 12 22 12s0 3.255-.418 4.814a2.504 2.504 0 0 1-1.768 1.768c-1.56.419-7.814.419-7.814.419s-6.255 0-7.814-.419a2.505 2.505 0 0 1-1.768-1.768C2 15.255 2 12 2 12s0-3.255.417-4.814a2.507 2.507 0 0 1 1.768-1.768C5.744 5 11.998 5 11.998 5s6.255 0 7.814.418ZM15.194 12 10 15V9l5.194 3Z\"\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t/>\n\t\t</svg>\n\t),\n}\n\n// Helper function to get URL from link\nfunction getLinkUrl(link: {\n\ttype?: (\"reference\" | \"custom\") | null\n\treference?:\n\t\t| { relationTo: \"pages\"; value: number | Page }\n\t\t| { relationTo: \"posts\"; value: number | Post }\n\t\t| null\n\turl?: string | null\n}): string {\n\tif (link.type === \"reference\" && link.reference) {\n\t\tconst value = link.reference.value\n\t\tif (typeof value === \"object\" && \"slug\" in value) {\n\t\t\tconst prefix = link.reference.relationTo === \"posts\" ? \"/posts\" : \"\"\n\t\t\treturn `${prefix}/${value.slug}`\n\t\t}\n\t}\n\treturn link.url || \"#\"\n}\n\nexport const FooterClient: React.FC<FooterClientProps> = ({ data }) => {\n\tconst currentYear = new Date().getFullYear()\n\tconst [email, setEmail] = useState(\"\")\n\tconst [isSubmitting, setIsSubmitting] = useState(false)\n\tconst [message, setMessage] = useState<{ type: \"success\" | \"error\"; text: string } | null>(null)\n\n\tconst { columns, socialLinks, newsletter, copyrightText, bottomLinks } = data\n\n\tconst handleNewsletterSubmit = async (e: React.FormEvent) => {\n\t\te.preventDefault()\n\t\tif (!email || isSubmitting) return\n\n\t\tsetIsSubmitting(true)\n\t\tsetMessage(null)\n\n\t\ttry {\n\t\t\tconst response = await fetch(\"/api/newsletter\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ email }),\n\t\t\t})\n\n\t\t\tconst result = await response.json()\n\n\t\t\tif (result.success) {\n\t\t\t\tsetMessage({ type: \"success\", text: result.message })\n\t\t\t\tsetEmail(\"\")\n\t\t\t} else {\n\t\t\t\tsetMessage({ type: \"error\", text: result.message })\n\t\t\t}\n\t\t} catch {\n\t\t\tsetMessage({ type: \"error\", text: \"Something went wrong. Please try again.\" })\n\t\t} finally {\n\t\t\tsetIsSubmitting(false)\n\t\t}\n\t}\n\n\t// Check if any social links are configured\n\tconst hasSocialLinks =\n\t\tsocialLinks?.twitter ||\n\t\tsocialLinks?.instagram ||\n\t\tsocialLinks?.linkedin ||\n\t\tsocialLinks?.github ||\n\t\tsocialLinks?.youtube\n\n\treturn (\n\t\t<footer className=\"mt-auto border-t border-border bg-background\">\n\t\t\t{/* Main Footer Content */}\n\t\t\t<div className=\"container mx-auto px-4 py-12 lg:py-16\">\n\t\t\t\t<div className=\"grid grid-cols-2 gap-8 md:grid-cols-3 lg:grid-cols-6\">\n\t\t\t\t\t{/* Link Columns */}\n\t\t\t\t\t{columns?.map((column) => (\n\t\t\t\t\t\t<div key={column.id || column.title} className=\"col-span-1\">\n\t\t\t\t\t\t\t<h3 className=\"mb-4 text-sm font-medium text-foreground\">{column.title}</h3>\n\t\t\t\t\t\t\t<ul className=\"space-y-3\">\n\t\t\t\t\t\t\t\t{column.links?.map((linkItem) => (\n\t\t\t\t\t\t\t\t\t<li key={linkItem.id || linkItem.link.label}>\n\t\t\t\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\t\t\t\thref={getLinkUrl(linkItem.link)}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-sm text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\t\t\t\t{...(linkItem.link.newTab\n\t\t\t\t\t\t\t\t\t\t\t\t? { target: \"_blank\", rel: \"noopener noreferrer\" }\n\t\t\t\t\t\t\t\t\t\t\t\t: {})}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{linkItem.link.label}\n\t\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{/* Newsletter Column */}\n\t\t\t\t\t{newsletter?.enabled && (\n\t\t\t\t\t\t<div className=\"col-span-2 md:col-span-3 lg:col-span-2\">\n\t\t\t\t\t\t\t<h3 className=\"mb-4 text-sm font-medium text-foreground\">\n\t\t\t\t\t\t\t\t{newsletter.title || \"Newsletter\"}\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t<p className=\"mb-4 text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t{newsletter.description || \"Stay up to date with the latest updates.\"}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t<form\n\t\t\t\t\t\t\t\tonSubmit={handleNewsletterSubmit}\n\t\t\t\t\t\t\t\tclassName=\"space-y-3\"\n\t\t\t\t\t\t\t\tsuppressHydrationWarning\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\t\t\tplaceholder={newsletter.placeholder || \"Enter your email\"}\n\t\t\t\t\t\t\t\t\t\tvalue={email}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) => setEmail(e.target.value)}\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex-1\"\n\t\t\t\t\t\t\t\t\t\tdisabled={isSubmitting}\n\t\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\t\tsuppressHydrationWarning\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<Button type=\"submit\" disabled={isSubmitting} suppressHydrationWarning>\n\t\t\t\t\t\t\t\t\t\t{isSubmitting ? \"...\" : newsletter.buttonText || \"Subscribe\"}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{message && (\n\t\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"text-sm\",\n\t\t\t\t\t\t\t\t\t\t\tmessage.type === \"success\" ? \"text-green-600\" : \"text-red-600\",\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{message.text}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</form>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Social Links */}\n\t\t\t\t{hasSocialLinks && (\n\t\t\t\t\t<div className=\"mt-10 flex items-center gap-4 border-t border-border pt-8\">\n\t\t\t\t\t\t{socialLinks?.twitter && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={socialLinks.twitter}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\taria-label=\"X (Twitter)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{SocialIcons.twitter}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{socialLinks?.instagram && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={socialLinks.instagram}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\taria-label=\"Instagram\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{SocialIcons.instagram}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{socialLinks?.linkedin && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={socialLinks.linkedin}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\taria-label=\"LinkedIn\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{SocialIcons.linkedin}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{socialLinks?.github && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={socialLinks.github}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\taria-label=\"GitHub\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{SocialIcons.github}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{socialLinks?.youtube && (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={socialLinks.youtube}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\taria-label=\"YouTube\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{SocialIcons.youtube}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Bottom Bar */}\n\t\t\t<div className=\"border-t border-border\">\n\t\t\t\t<div className=\"container mx-auto flex flex-col items-center justify-between gap-4 px-4 py-6 sm:flex-row\">\n\t\t\t\t\t{/* Logo and Copyright */}\n\t\t\t\t\t<div className=\"flex items-center gap-4\">\n\t\t\t\t\t\t<Link href=\"/\" className=\"flex items-center\">\n\t\t\t\t\t\t\t<Logo variant=\"auto\" className=\"h-6 w-6\" />\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t© {currentYear} {copyrightText || \"DirectoryHub\"}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Bottom Links and Theme Selector */}\n\t\t\t\t\t<div className=\"flex items-center gap-6\">\n\t\t\t\t\t\t{bottomLinks?.map((linkItem) => (\n\t\t\t\t\t\t\t<Link\n\t\t\t\t\t\t\t\tkey={linkItem.id || linkItem.link.label}\n\t\t\t\t\t\t\t\thref={getLinkUrl(linkItem.link)}\n\t\t\t\t\t\t\t\tclassName=\"text-sm text-muted-foreground transition-colors hover:text-foreground\"\n\t\t\t\t\t\t\t\t{...(linkItem.link.newTab ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {})}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{linkItem.link.label}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<ThemeSelector />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</footer>\n\t)\n}\n",
57
57
  "marketing/payload/src/Footer/Component.tsx": "import { getCachedGlobal } from \"@/utilities/getGlobals\"\n\nimport type { Footer as FooterType } from \"@/payload-types\"\n\nimport { FooterClient } from \"./Component.client\"\n\nexport async function Footer() {\n\tconst footerData: FooterType = await getCachedGlobal(\"footer\", 1)()\n\n\treturn <FooterClient data={footerData} />\n}\n",
@@ -208,6 +208,7 @@ export const EMBEDDED_TEMPLATES: Record<string, string> = {
208
208
  "marketing/payload/src/components/ui/pagination.tsx": "import type { ButtonProps } from \"@/components/ui/button\"\n\nimport { buttonVariants } from \"@/components/ui/button\"\nimport { cn } from \"@/utilities/ui\"\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\"\nimport type * as React from \"react\"\n\nconst Pagination = ({ className, ...props }: React.ComponentProps<\"nav\">) => (\n\t<nav\n\t\taria-label=\"pagination\"\n\t\tclassName={cn(\"mx-auto flex w-full justify-center\", className)}\n\t\trole=\"navigation\"\n\t\t{...props}\n\t/>\n)\n\nconst PaginationContent: React.FC<\n\t{ ref?: React.Ref<HTMLUListElement> } & React.HTMLAttributes<HTMLUListElement>\n> = ({ className, ref, ...props }) => (\n\t<ul className={cn(\"flex flex-row items-center gap-1\", className)} ref={ref} {...props} />\n)\n\nconst PaginationItem: React.FC<\n\t{ ref?: React.Ref<HTMLLIElement> } & React.HTMLAttributes<HTMLLIElement>\n> = ({ className, ref, ...props }) => <li className={cn(\"\", className)} ref={ref} {...props} />\n\ntype PaginationLinkProps = {\n\tisActive?: boolean\n} & Pick<ButtonProps, \"size\"> &\n\tReact.ComponentProps<\"button\">\n\nconst PaginationLink = ({ className, isActive, size = \"icon\", ...props }: PaginationLinkProps) => (\n\t<button\n\t\taria-current={isActive ? \"page\" : undefined}\n\t\tclassName={cn(\n\t\t\tbuttonVariants({\n\t\t\t\tsize,\n\t\t\t\tvariant: isActive ? \"outline\" : \"ghost\",\n\t\t\t}),\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n)\n\nconst PaginationPrevious = ({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof PaginationLink>) => (\n\t<PaginationLink\n\t\taria-label=\"Go to previous page\"\n\t\tclassName={cn(\"gap-1 pl-2.5\", className)}\n\t\tsize=\"default\"\n\t\t{...props}\n\t>\n\t\t<ChevronLeft className=\"h-4 w-4\" />\n\t\t<span>Previous</span>\n\t</PaginationLink>\n)\n\nconst PaginationNext = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => (\n\t<PaginationLink\n\t\taria-label=\"Go to next page\"\n\t\tclassName={cn(\"gap-1 pr-2.5\", className)}\n\t\tsize=\"default\"\n\t\t{...props}\n\t>\n\t\t<span>Next</span>\n\t\t<ChevronRight className=\"h-4 w-4\" />\n\t</PaginationLink>\n)\n\nconst PaginationEllipsis = ({ className, ...props }: React.ComponentProps<\"span\">) => (\n\t<span\n\t\taria-hidden\n\t\tclassName={cn(\"flex h-9 w-9 items-center justify-center\", className)}\n\t\t{...props}\n\t>\n\t\t<MoreHorizontal className=\"h-4 w-4\" />\n\t\t<span className=\"sr-only\">More pages</span>\n\t</span>\n)\n\nexport {\n\tPagination,\n\tPaginationContent,\n\tPaginationEllipsis,\n\tPaginationItem,\n\tPaginationLink,\n\tPaginationNext,\n\tPaginationPrevious,\n}\n",
209
209
  "marketing/payload/src/components/ui/select.tsx": "\"use client\"\n\nimport { cn } from \"@/utilities/ui\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { Check, ChevronDown, ChevronUp } from \"lucide-react\"\nimport type * as React from \"react\"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger: React.FC<\n\t{ ref?: React.Ref<HTMLButtonElement> } & React.ComponentProps<typeof SelectPrimitive.Trigger>\n> = ({ children, className, ref, ...props }) => (\n\t<SelectPrimitive.Trigger\n\t\tclassName={cn(\n\t\t\t\"flex h-10 w-full items-center justify-between rounded border border-input bg-background px-3 py-2 text-inherit ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1\",\n\t\t\tclassName,\n\t\t)}\n\t\tref={ref}\n\t\t{...props}\n\t>\n\t\t{children}\n\t\t<SelectPrimitive.Icon asChild>\n\t\t\t<ChevronDown className=\"h-4 w-4 opacity-50\" />\n\t\t</SelectPrimitive.Icon>\n\t</SelectPrimitive.Trigger>\n)\n\nconst SelectScrollUpButton: React.FC<\n\t{ ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>\n> = ({ className, ref, ...props }) => (\n\t<SelectPrimitive.ScrollUpButton\n\t\tclassName={cn(\"flex cursor-default items-center justify-center py-1\", className)}\n\t\tref={ref}\n\t\t{...props}\n\t>\n\t\t<ChevronUp className=\"h-4 w-4\" />\n\t</SelectPrimitive.ScrollUpButton>\n)\n\nconst SelectScrollDownButton: React.FC<\n\t{ ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<\n\t\ttypeof SelectPrimitive.ScrollDownButton\n\t>\n> = ({ className, ref, ...props }) => (\n\t<SelectPrimitive.ScrollDownButton\n\t\tclassName={cn(\"flex cursor-default items-center justify-center py-1\", className)}\n\t\tref={ref}\n\t\t{...props}\n\t>\n\t\t<ChevronDown className=\"h-4 w-4\" />\n\t</SelectPrimitive.ScrollDownButton>\n)\n\nconst SelectContent: React.FC<\n\t{\n\t\tref?: React.Ref<HTMLDivElement>\n\t} & React.ComponentProps<typeof SelectPrimitive.Content>\n> = ({ children, className, position = \"popper\", ref, ...props }) => (\n\t<SelectPrimitive.Portal>\n\t\t<SelectPrimitive.Content\n\t\t\tclassName={cn(\n\t\t\t\t\"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded border bg-card text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tposition={position}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SelectScrollUpButton />\n\t\t\t<SelectPrimitive.Viewport\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"p-1\",\n\t\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\t\"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</SelectPrimitive.Viewport>\n\t\t\t<SelectScrollDownButton />\n\t\t</SelectPrimitive.Content>\n\t</SelectPrimitive.Portal>\n)\n\nconst SelectLabel: React.FC<\n\t{ ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<typeof SelectPrimitive.Label>\n> = ({ className, ref, ...props }) => (\n\t<SelectPrimitive.Label\n\t\tclassName={cn(\"py-1.5 pl-8 pr-2 text-sm font-semibold\", className)}\n\t\tref={ref}\n\t\t{...props}\n\t/>\n)\n\nconst SelectItem: React.FC<\n\t{ ref?: React.Ref<HTMLDivElement>; value: string } & React.ComponentProps<\n\t\ttypeof SelectPrimitive.Item\n\t>\n> = ({ children, className, ref, ...props }) => (\n\t<SelectPrimitive.Item\n\t\tclassName={cn(\n\t\t\t\"relative flex w-full cursor-default select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n\t\t\tclassName,\n\t\t)}\n\t\tref={ref}\n\t\t{...props}\n\t>\n\t\t<span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n\t\t\t<SelectPrimitive.ItemIndicator>\n\t\t\t\t<Check className=\"h-4 w-4\" />\n\t\t\t</SelectPrimitive.ItemIndicator>\n\t\t</span>\n\n\t\t<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n\t</SelectPrimitive.Item>\n)\n\nconst SelectSeparator: React.FC<\n\t{ ref?: React.Ref<HTMLDivElement> } & React.ComponentProps<typeof SelectPrimitive.Separator>\n> = ({ className, ref, ...props }) => (\n\t<SelectPrimitive.Separator\n\t\tclassName={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n\t\tref={ref}\n\t\t{...props}\n\t/>\n)\n\nexport {\n\tSelect,\n\tSelectContent,\n\tSelectGroup,\n\tSelectItem,\n\tSelectLabel,\n\tSelectScrollDownButton,\n\tSelectScrollUpButton,\n\tSelectSeparator,\n\tSelectTrigger,\n\tSelectValue,\n}\n",
210
210
  "marketing/payload/src/components/ui/textarea.tsx": "import { cn } from \"@/utilities/ui\"\nimport type * as React from \"react\"\n\nconst Textarea: React.FC<\n\t{\n\t\tref?: React.Ref<HTMLTextAreaElement>\n\t} & React.TextareaHTMLAttributes<HTMLTextAreaElement>\n> = ({ className, ref, ...props }) => {\n\treturn (\n\t\t<textarea\n\t\t\tclassName={cn(\n\t\t\t\t\"flex min-h-[80px] w-full rounded border border-border bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Textarea }\n",
211
+ "marketing/payload/src/cssVariables.ts": "export const cssVariables = {\n breakpoints: {\n xs: 400,\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n },\n}\n",
211
212
  "marketing/payload/src/endpoints/seed/contact-form.ts": "import type { RequiredDataFromCollectionSlug } from \"payload\"\n\nexport const contactForm: RequiredDataFromCollectionSlug<\"forms\"> = {\n\tconfirmationMessage: {\n\t\troot: {\n\t\t\ttype: \"root\",\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"heading\",\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\ttext: \"The contact form has been submitted successfully.\",\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdirection: \"ltr\",\n\t\t\t\t\tformat: \"\",\n\t\t\t\t\tindent: 0,\n\t\t\t\t\ttag: \"h2\",\n\t\t\t\t\tversion: 1,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdirection: \"ltr\",\n\t\t\tformat: \"\",\n\t\t\tindent: 0,\n\t\t\tversion: 1,\n\t\t},\n\t},\n\tconfirmationType: \"message\",\n\tcreatedAt: \"2023-01-12T21:47:41.374Z\",\n\temails: [\n\t\t{\n\t\t\temailFrom: '\"Payload\" \\u003Cdemo@payloadcms.com\\u003E',\n\t\t\temailTo: \"{{email}}\",\n\t\t\tmessage: {\n\t\t\t\troot: {\n\t\t\t\t\ttype: \"root\",\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"paragraph\",\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\t\t\ttext: \"Your contact form submission was successfully received.\",\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdirection: \"ltr\",\n\t\t\t\t\t\t\tformat: \"\",\n\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\ttextFormat: 0,\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdirection: \"ltr\",\n\t\t\t\t\tformat: \"\",\n\t\t\t\t\tindent: 0,\n\t\t\t\t\tversion: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tsubject: \"You've received a new message.\",\n\t\t},\n\t],\n\tfields: [\n\t\t{\n\t\t\tname: \"full-name\",\n\t\t\tblockName: \"full-name\",\n\t\t\tblockType: \"text\",\n\t\t\tlabel: \"Full Name\",\n\t\t\trequired: true,\n\t\t\twidth: 100,\n\t\t},\n\t\t{\n\t\t\tname: \"email\",\n\t\t\tblockName: \"email\",\n\t\t\tblockType: \"email\",\n\t\t\tlabel: \"Email\",\n\t\t\trequired: true,\n\t\t\twidth: 100,\n\t\t},\n\t\t{\n\t\t\tname: \"phone\",\n\t\t\tblockName: \"phone\",\n\t\t\tblockType: \"number\",\n\t\t\tlabel: \"Phone\",\n\t\t\trequired: false,\n\t\t\twidth: 100,\n\t\t},\n\t\t{\n\t\t\tname: \"message\",\n\t\t\tblockName: \"message\",\n\t\t\tblockType: \"textarea\",\n\t\t\tlabel: \"Message\",\n\t\t\trequired: true,\n\t\t\twidth: 100,\n\t\t},\n\t],\n\tredirect: undefined,\n\tsubmitButtonLabel: \"Submit\",\n\ttitle: \"Contact Form\",\n\tupdatedAt: \"2023-01-12T21:47:41.374Z\",\n}\n",
212
213
  "marketing/payload/src/endpoints/seed/contact-page.ts": "import type { Form } from \"@/payload-types\"\nimport type { RequiredDataFromCollectionSlug } from \"payload\"\n\ntype ContactArgs = {\n\tcontactForm: Form\n}\n\nexport const contact: (args: ContactArgs) => RequiredDataFromCollectionSlug<\"pages\"> = ({\n\tcontactForm,\n}) => {\n\treturn {\n\t\tslug: \"contact\",\n\t\t_status: \"published\",\n\t\thero: {\n\t\t\ttype: \"none\",\n\t\t},\n\t\tlayout: [\n\t\t\t{\n\t\t\t\tblockType: \"formBlock\",\n\t\t\t\tenableIntro: true,\n\t\t\t\tform: contactForm,\n\t\t\t\tintroContent: {\n\t\t\t\t\troot: {\n\t\t\t\t\t\ttype: \"root\",\n\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"heading\",\n\t\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\t\t\t\ttext: \"Example contact form:\",\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tdirection: \"ltr\",\n\t\t\t\t\t\t\t\tformat: \"\",\n\t\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\t\ttag: \"h3\",\n\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdirection: \"ltr\",\n\t\t\t\t\t\tformat: \"\",\n\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\ttitle: \"Contact\",\n\t}\n}\n",
213
214
  "marketing/payload/src/endpoints/seed/directoryhub/about.ts": "import type { Form, Page } from \"@/payload-types\"\nimport { createParagraph } from \"./richtext-helper\"\n\ntype AboutArgs = {\n\tcontactForm: Form\n}\n\nexport const directoryHubAbout = ({ contactForm }: AboutArgs): Partial<Page> => {\n\treturn {\n\t\tslug: \"about\",\n\t\t_status: \"published\",\n\t\thero: {\n\t\t\ttype: \"lowImpact\",\n\t\t\trichText: {\n\t\t\t\troot: {\n\t\t\t\t\ttype: \"root\",\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"heading\",\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\t\t\ttext: \"We help entrepreneurs build directory businesses\",\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdirection: \"ltr\" as const,\n\t\t\t\t\t\t\tformat: \"\" as const,\n\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\ttag: \"h1\",\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"paragraph\",\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\t\t\ttext: \"DirectoryHub makes it easy for anyone to launch, monetize, and grow niche directory websites — without writing code.\",\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdirection: \"ltr\" as const,\n\t\t\t\t\t\t\tformat: \"\" as const,\n\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\ttextFormat: 0,\n\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdirection: \"ltr\" as const,\n\t\t\t\t\tformat: \"\" as const,\n\t\t\t\t\tindent: 0,\n\t\t\t\t\tversion: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tlayout: [\n\t\t\t// Mission Section\n\t\t\t{\n\t\t\t\tblockType: \"featureShowcase\",\n\t\t\t\tblockName: \"Our Mission\",\n\t\t\t\tlabel: \"Our Mission\",\n\t\t\t\theadline: \"Democratizing the directory business model\",\n\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\"Directory websites remain one of the most sustainable online business models, yet building one traditionally requires significant technical expertise. We believe anyone with niche knowledge should be able to turn that expertise into a profitable directory business. DirectoryHub handles the technical complexity so you can focus on what matters: curating great content and growing your community.\",\n\t\t\t\t),\n\t\t\t\tlink: {\n\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\turl: \"/pricing\",\n\t\t\t\t\tlabel: \"View pricing\",\n\t\t\t\t\tappearance: \"default\",\n\t\t\t\t},\n\t\t\t\timagePosition: \"right\",\n\t\t\t\tfeatures: [\n\t\t\t\t\t{ text: \"No coding required\" },\n\t\t\t\t\t{ text: \"Built-in monetization\" },\n\t\t\t\t\t{ text: \"Enterprise-grade SEO\" },\n\t\t\t\t\t{ text: \"Scale as you grow\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t// Stats Banner\n\t\t\t{\n\t\t\t\tblockType: \"proofBanner\",\n\t\t\t\tblockName: \"Impact Stats\",\n\t\t\t\tstyle: \"withBackground\",\n\t\t\t\theadline: \"Trusted by directory builders worldwide\",\n\t\t\t\tsubtext:\n\t\t\t\t\t\"Join hundreds of entrepreneurs who have launched successful directories with DirectoryHub\",\n\t\t\t},\n\t\t\t// Values Grid\n\t\t\t{\n\t\t\t\tblockType: \"bentoFeatures\",\n\t\t\t\tblockName: \"Our Values\",\n\t\t\t\theading: \"What we stand for\",\n\t\t\t\tsubheading: \"The principles that guide everything we build\",\n\t\t\t\tfeatures: [\n\t\t\t\t\t{\n\t\t\t\t\t\tsize: \"small\",\n\t\t\t\t\t\tstyle: \"gradient\",\n\t\t\t\t\t\ticon: \"zap\",\n\t\t\t\t\t\ttitle: \"Simplicity First\",\n\t\t\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\t\t\"We remove complexity so you can focus on building your business.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsize: \"small\",\n\t\t\t\t\t\tstyle: \"accent\",\n\t\t\t\t\t\ticon: \"rocket\",\n\t\t\t\t\t\ttitle: \"Built for Growth\",\n\t\t\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\t\t\"Every feature is designed to help you scale sustainably.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsize: \"small\",\n\t\t\t\t\t\tstyle: \"default\",\n\t\t\t\t\t\ticon: \"shield\",\n\t\t\t\t\t\ttitle: \"Transparency\",\n\t\t\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\t\t\"Clear pricing, no hidden fees, honest communication always.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsize: \"small\",\n\t\t\t\t\t\tstyle: \"primary\",\n\t\t\t\t\t\ticon: \"users\",\n\t\t\t\t\t\ttitle: \"Customer Success\",\n\t\t\t\t\t\tdescription: createParagraph(\"Your success is our success. We invest in your growth.\"),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsize: \"small\",\n\t\t\t\t\t\tstyle: \"default\",\n\t\t\t\t\t\ticon: \"globe\",\n\t\t\t\t\t\ttitle: \"Quality Matters\",\n\t\t\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\t\t\"We build tools that help you maintain high-quality directories.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tsize: \"small\",\n\t\t\t\t\t\tstyle: \"default\",\n\t\t\t\t\t\ticon: \"settings\",\n\t\t\t\t\t\ttitle: \"Continuous Innovation\",\n\t\t\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\t\t\"We constantly improve our platform based on customer feedback.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t// Our Story\n\t\t\t{\n\t\t\t\tblockType: \"featureShowcase\",\n\t\t\t\tblockName: \"Our Story\",\n\t\t\t\tlabel: \"Our Story\",\n\t\t\t\theadline: \"From frustration to solution\",\n\t\t\t\tdescription: createParagraph(\n\t\t\t\t\t\"DirectoryHub was born when our founders tried to build a niche directory and discovered how much technical overhead was involved. After months of custom development for what seemed like a simple project, we realized there had to be a better way. We built DirectoryHub to be the platform we wished existed — one that handles all the technical complexity while giving directory builders complete control over their business.\",\n\t\t\t\t),\n\t\t\t\tlink: {\n\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\turl: \"/sign-up\",\n\t\t\t\t\tlabel: \"Start building free\",\n\t\t\t\t\tappearance: \"default\",\n\t\t\t\t},\n\t\t\t\timagePosition: \"left\",\n\t\t\t\tfeatures: [\n\t\t\t\t\t{ text: \"Founded by directory builders\" },\n\t\t\t\t\t{ text: \"Bootstrapped and profitable\" },\n\t\t\t\t\t{ text: \"Customer-funded development\" },\n\t\t\t\t\t{ text: \"Global remote team\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t// Contact Section\n\t\t\t{\n\t\t\t\tblockType: \"content\",\n\t\t\t\tblockName: \"Contact Header\",\n\t\t\t\tcolumns: [\n\t\t\t\t\t{\n\t\t\t\t\t\trichText: {\n\t\t\t\t\t\t\troot: {\n\t\t\t\t\t\t\t\ttype: \"root\",\n\t\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"heading\",\n\t\t\t\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\t\t\t\t\t\ttext: \"Get in Touch\",\n\t\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tdirection: \"ltr\" as const,\n\t\t\t\t\t\t\t\t\t\tformat: \"\" as const,\n\t\t\t\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\t\t\t\ttag: \"h2\",\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: \"paragraph\",\n\t\t\t\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\t\t\tdetail: 0,\n\t\t\t\t\t\t\t\t\t\t\t\tformat: 0,\n\t\t\t\t\t\t\t\t\t\t\t\tmode: \"normal\",\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: \"\",\n\t\t\t\t\t\t\t\t\t\t\t\ttext: \"Have questions about DirectoryHub? We'd love to hear from you. Send us a message and our team will respond within 24 hours.\",\n\t\t\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tdirection: \"ltr\" as const,\n\t\t\t\t\t\t\t\t\t\tformat: \"\" as const,\n\t\t\t\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\t\t\t\ttextFormat: 0,\n\t\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tdirection: \"ltr\" as const,\n\t\t\t\t\t\t\t\tformat: \"\" as const,\n\t\t\t\t\t\t\t\tindent: 0,\n\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsize: \"full\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t// Contact Form\n\t\t\t{\n\t\t\t\tblockType: \"formBlock\",\n\t\t\t\tblockName: \"Contact Form\",\n\t\t\t\tform: contactForm.id,\n\t\t\t\tenableIntro: false,\n\t\t\t},\n\t\t\t// Final CTA\n\t\t\t{\n\t\t\t\tblockType: \"proofBanner\",\n\t\t\t\tblockName: \"Footer CTA\",\n\t\t\t\tstyle: \"centered\",\n\t\t\t\theadline: \"Ready to build your directory?\",\n\t\t\t\tsubtext: \"Join hundreds of entrepreneurs building successful directory businesses.\",\n\t\t\t\tlinks: [\n\t\t\t\t\t{\n\t\t\t\t\t\tlink: {\n\t\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\t\tappearance: \"default\",\n\t\t\t\t\t\t\tlabel: \"Start for free\",\n\t\t\t\t\t\t\turl: \"/sign-up\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tlink: {\n\t\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\t\tappearance: \"outline\",\n\t\t\t\t\t\t\tlabel: \"View pricing\",\n\t\t\t\t\t\t\turl: \"/pricing\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t\tmeta: {\n\t\t\tdescription:\n\t\t\t\t\"Learn about DirectoryHub — the platform that makes it easy to build, monetize, and grow directory websites. Founded by directory builders, for directory builders.\",\n\t\t\ttitle: \"About DirectoryHub — Our Mission & Story\",\n\t\t},\n\t\ttitle: \"About\",\n\t}\n}\n",
@@ -39,6 +39,7 @@
39
39
  "class-variance-authority": "^0.7.1",
40
40
  "clsx": "^2.1.1",
41
41
  "cross-env": "^7.0.3",
42
+ "geist": "^1.3.0",
42
43
  "lucide-react": "^0.562.0",
43
44
  "next": "^15.4.10",
44
45
  "payload": "^3.70.0",
@@ -0,0 +1,10 @@
1
+ export const cssVariables = {
2
+ breakpoints: {
3
+ xs: 400,
4
+ sm: 640,
5
+ md: 768,
6
+ lg: 1024,
7
+ xl: 1280,
8
+ '2xl': 1536,
9
+ },
10
+ }