kofi-stack-template-generator 2.1.46 → 2.1.48

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.
@@ -13,7 +13,7 @@ import { ThemeSelector } from "@/providers/Theme/ThemeSelector"
13
13
  import { cn } from "@/utilities/ui"
14
14
 
15
15
  interface FooterClientProps {
16
- data: Footer
16
+ data: Footer | null
17
17
  }
18
18
 
19
19
  // Social icons as inline SVGs for flexibility
@@ -82,6 +82,20 @@ export const FooterClient: React.FC<FooterClientProps> = ({ data }) => {
82
82
  const [isSubmitting, setIsSubmitting] = useState(false)
83
83
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null)
84
84
 
85
+ // Show minimal footer when database isn't initialized yet
86
+ if (!data) {
87
+ return (
88
+ <footer className="mt-auto border-t border-border bg-background">
89
+ <div className="container mx-auto flex flex-col items-center justify-between gap-4 px-4 py-6 sm:flex-row">
90
+ <p className="text-sm text-muted-foreground">
91
+ Site not configured yet. Visit <Link href="/admin" className="underline hover:text-foreground">/admin</Link> to set up.
92
+ </p>
93
+ <ThemeSelector />
94
+ </div>
95
+ </footer>
96
+ )
97
+ }
98
+
85
99
  const { columns, socialLinks, newsletter, copyrightText, bottomLinks } = data
86
100
 
87
101
  const handleNewsletterSubmit = async (e: React.FormEvent) => {
@@ -5,7 +5,7 @@ import type { Footer as FooterType } from "@/payload-types"
5
5
  import { FooterClient } from "./Component.client"
6
6
 
7
7
  export async function Footer() {
8
- const footerData: FooterType = await getCachedGlobal("footer", 1)()
8
+ const footerData = (await getCachedGlobal("footer", 1)()) as FooterType | null
9
9
 
10
10
  return <FooterClient data={footerData} />
11
11
  }
@@ -12,7 +12,7 @@ import { MobileMenu } from "./MobileMenu"
12
12
  import { HeaderNav } from "./Nav"
13
13
 
14
14
  interface HeaderClientProps {
15
- data: Header
15
+ data: Header | null
16
16
  }
17
17
 
18
18
  // Helper to get href from link data
@@ -57,6 +57,22 @@ export const HeaderClient: React.FC<HeaderClientProps> = ({ data }) => {
57
57
  return rightButtonItems?.[0]
58
58
  }, [data?.navItems])
59
59
 
60
+ // Show setup header when database isn't initialized yet
61
+ if (!data) {
62
+ return (
63
+ <header className="sticky top-0 z-20 border-b border-border bg-background">
64
+ <div className="container mx-auto px-4 h-16 flex justify-between items-center">
65
+ <div className="flex items-center gap-2">
66
+ <span className="text-xl font-semibold">Welcome</span>
67
+ </div>
68
+ <Button asChild size="sm">
69
+ <Link href="/admin">Setup Site →</Link>
70
+ </Button>
71
+ </div>
72
+ </header>
73
+ )
74
+ }
75
+
60
76
  return (
61
77
  <header
62
78
  className="sticky top-0 z-20 border-b border-border bg-background"
@@ -4,7 +4,7 @@ import { HeaderClient } from "./Component.client"
4
4
  import type { Header as HeaderType } from "@/payload-types"
5
5
 
6
6
  export async function Header() {
7
- const headerData: HeaderType = await getCachedGlobal("header", 1)()
7
+ const headerData = (await getCachedGlobal("header", 1)()) as HeaderType | null
8
8
 
9
9
  return <HeaderClient data={headerData} />
10
10
  }
@@ -160,7 +160,7 @@ export const securityPage = (): Partial<Page> => {
160
160
  {
161
161
  size: "small",
162
162
  style: "accent",
163
- icon: "lock",
163
+ icon: "shield",
164
164
  title: "Zero Trust",
165
165
  description: createParagraph("Verify every request, every time."),
166
166
  },
@@ -131,7 +131,7 @@ export const integrationsPage = (): Partial<Page> => {
131
131
  {
132
132
  size: "small",
133
133
  style: "gradient",
134
- icon: "messageSquare",
134
+ icon: "globe",
135
135
  title: "Communication",
136
136
  description: createParagraph(
137
137
  "Slack, Microsoft Teams, Discord, and email integrations.",
@@ -149,7 +149,7 @@ export const integrationsPage = (): Partial<Page> => {
149
149
  {
150
150
  size: "small",
151
151
  style: "default",
152
- icon: "folder",
152
+ icon: "layers",
153
153
  title: "Project Management",
154
154
  description: createParagraph(
155
155
  "Jira, Asana, Monday.com, Trello integrations.",
@@ -160,7 +160,7 @@ export const marketingPage = (): Partial<Page> => {
160
160
  {
161
161
  size: "small",
162
162
  style: "accent",
163
- icon: "folder",
163
+ icon: "layers",
164
164
  title: "Project Templates",
165
165
  description: createParagraph("Pre-built templates for common campaigns."),
166
166
  },
@@ -188,7 +188,7 @@ export const marketingPage = (): Partial<Page> => {
188
188
  {
189
189
  size: "small",
190
190
  style: "default",
191
- icon: "messageSquare",
191
+ icon: "globe",
192
192
  title: "Collaboration",
193
193
  description: createParagraph("Comments, feedback, and approvals in context."),
194
194
  },
@@ -188,7 +188,7 @@ export const productPage = (): Partial<Page> => {
188
188
  {
189
189
  size: "small",
190
190
  style: "default",
191
- icon: "messageSquare",
191
+ icon: "users",
192
192
  title: "Stakeholder Updates",
193
193
  description: createParagraph("Keep leadership informed automatically."),
194
194
  },
@@ -64,9 +64,9 @@ export default buildConfig({
64
64
  pool: {
65
65
  connectionString: process.env.DATABASE_URL || "",
66
66
  },
67
- // Disable auto-push in dev mode to prevent constraint name truncation issues
68
- // Use migrations instead: pnpm payload migrate
69
- push: false,
67
+ // Auto-sync schema in development for better DX (first launch works immediately)
68
+ // In production, use explicit migrations: pnpm payload migrate
69
+ push: process.env.NODE_ENV !== "production",
70
70
  }),
71
71
  collections: [Pages, Posts, Media, Categories, FAQs, Users],
72
72
  cors: [getServerSideURL()].filter(Boolean),
@@ -7,14 +7,21 @@ import { getPayload } from "payload"
7
7
  type Global = keyof Config["globals"]
8
8
 
9
9
  async function getGlobal(slug: Global, depth = 0) {
10
- const payload = await getPayload({ config: configPromise })
10
+ try {
11
+ const payload = await getPayload({ config: configPromise })
11
12
 
12
- const global = await payload.findGlobal({
13
- slug,
14
- depth,
15
- })
13
+ const global = await payload.findGlobal({
14
+ slug,
15
+ depth,
16
+ })
16
17
 
17
- return global
18
+ return global
19
+ } catch (error) {
20
+ // Database tables may not exist yet on first launch
21
+ // Return null so components can show a setup UI instead of crashing
22
+ console.warn(`Could not fetch global "${String(slug)}". Database may not be initialized yet.`)
23
+ return null
24
+ }
18
25
  }
19
26
 
20
27
  /**