I'm working on my own template, and part of it is having Payload baked in. This is the setup I came up with (with help from Claude), but it seems to messy/over complicated. Can I get some quick feedback on this approach and if you have suggestions, I'd love to hear them!
I'm still working on the revalidation hook setup so when a user clicks save, it triggers a re-deploy so the site is always statically generated and fast.
// Enable ISR with on-demand revalidation for performance
export const revalidate = 3600; // Cache for 1 hour, revalidate on-demand via webhook
export default async function Home() {
// Try to fetch from CMS, fall back to static data if database is unavailable
let heroData: any;
let aboutData: any;
let projects: any;
// Check if we're in draft mode for live preview
const { isEnabled: isDraftMode } = await draftMode();
try {
const payload = await getPayload({ config });
// Fetch all CMS data in parallel for better performance
[heroData, aboutData, processData, projectsSection, contactSection, companyInfo, services, projects, testimonials] = await Promise.all([
payload.findGlobal({ slug: "hero-section", draft: isDraftMode }),
payload.findGlobal({ slug: "about-section", draft: isDraftMode }),
payload.find({
collection: "projects",
where: { featured: { equals: true } },
limit: 6,
draft: isDraftMode,
}),
]);
} catch (error) {
// Use fallback data when CMS is unavailable (e.g., during build without database)
console.warn("CMS unavailable, using fallback data:", error);
heroData = fallbackHeroData;
aboutData = fallbackAboutData;
projects = { docs: fallbackProjects };
}
// Extract background image URL if it's a Media object
const backgroundImage =
typeof heroData.backgroundImage === "object" && heroData.backgroundImage !== null
? (heroData.backgroundImage as any).url
: heroData.backgroundImage;
return (
<main className="min-h-screen">
{/* Hero Section - Data from CMS */}
<Hero
title={heroData.title as string}
subtitle={heroData.subtitle as string}
description={heroData.description as string}
primaryCTA={heroData.primaryCTA as any}
secondaryCTA={heroData.secondaryCTA as any}
backgroundImage={backgroundImage}
backgroundVideo={heroData.backgroundVideo as string}
overlay={heroData.overlay as boolean}
overlayOpacity={heroData.overlayOpacity as number}
/>
{/* About Section - Data from CMS */}
<AboutSection data={aboutData as AboutSectionData} />
{/* Featured Projects Section - Data from CMS */}
<FeaturedProjectsSection
data={projects.docs as Project[]}
title={projectsSection?.title}
/>
</main>
);
}