From aa4c8f30d4f11fa9089a55daeb6bc701751226fb Mon Sep 17 00:00:00 2001 From: Marius Ahsmus Date: Fri, 22 May 2026 17:17:43 +0200 Subject: [PATCH 01/30] feat: imporve footer & added section heading highlighting --- src/components/sections/FooterSection.tsx | 76 +++++++++++------------ src/components/sections/HeroSection.tsx | 8 +-- src/components/ui/Section.tsx | 35 +++++++++-- 3 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/components/sections/FooterSection.tsx b/src/components/sections/FooterSection.tsx index c0054ac0..b83227ee 100644 --- a/src/components/sections/FooterSection.tsx +++ b/src/components/sections/FooterSection.tsx @@ -37,31 +37,8 @@ export const FooterSection: React.FC = ({ locale, footer }) return ( -
-
- {(footer.groups ?? []).map((group) => ( -
-

- {group.heading} -

- {(group.items ?? []).map((item) => ( - trigger("medium")} - > -

- {item.label} -

- - ))} -
- ))} -
- -
- -
+
+
{"Code0 @@ -106,21 +83,44 @@ export const FooterSection: React.FC = ({ locale, footer })
-
+
+ {(footer.groups ?? []).map((group) => ( +
+

+ {group.heading} +

+ {(group.items ?? []).map((item) => ( + trigger("medium")} + > +

+ {item.label} +

+ + ))} +
+ ))} +
-
-
- {legalLinks.map((link) => ( - trigger("medium")}> - - {link.label} - - - ))} +
+ diff --git a/src/components/sections/HeroSection.tsx b/src/components/sections/HeroSection.tsx index 28929e72..08d50f6b 100644 --- a/src/components/sections/HeroSection.tsx +++ b/src/components/sections/HeroSection.tsx @@ -94,7 +94,7 @@ export function HeroSection({ content, imageSrc = "/code0_software.png" }: HeroS
-
+
{content.heading}
@@ -185,7 +185,7 @@ export function HeroSection({ content, imageSrc = "/code0_software.png" }: HeroS
-
+
{"Code0
diff --git a/src/components/ui/Section.tsx b/src/components/ui/Section.tsx index 8483e3fb..78f4f695 100644 --- a/src/components/ui/Section.tsx +++ b/src/components/ui/Section.tsx @@ -5,13 +5,37 @@ import { getLocaleFromPath, localizeHref } from "@/lib/i18n" import { ANIMATION_PRESETS, cn, type AnimationPreset } from "@/lib/utils" import { m as motion, type Variants } from "motion/react" import { usePathname } from "next/navigation" -import { createElement, ReactNode, useEffect, useRef, useState } from "react" +import { createElement, Fragment, ReactNode, useEffect, useRef, useState } from "react" interface SectionLinkButton { label?: string | null url?: string | null } +function hasHighlightedHeading(heading?: string | null) { + return Boolean(heading && /\*\*.*?\*\*/.test(heading)) +} + +function renderHighlightedHeading(heading?: string | null) { + if (!heading) return heading + + const parts = heading.split(/(\*\*.*?\*\*)/g) + + return parts.map((part, index) => { + const isHighlighted = part.startsWith("**") && part.endsWith("**") && part.length > 4 + + if (!isHighlighted) { + return {part} + } + + return ( + + {part.slice(2, -2)} + + ) + }) +} + interface SectionProps { children: ReactNode funnelType?: "center" | "left" @@ -80,6 +104,7 @@ export function Section({ }, } const headingTag = `h${headingLevel}` as const + const headingClassName = cn("text-4xl font-semibold", hasHighlightedHeading(heading) ? "text-white/50" : "text-white") useEffect(() => { const currentRef = sectionRef.current @@ -134,8 +159,8 @@ export function Section({ > {createElement( motion[headingTag], - { variants: staggerItem, className: "text-4xl text-white font-semibold" }, - heading, + { variants: staggerItem, className: headingClassName }, + renderHighlightedHeading(heading), )} {description && ( @@ -160,8 +185,8 @@ export function Section({ > {createElement( motion[headingTag], - { variants: staggerItem, className: "text-4xl text-white font-semibold" }, - heading, + { variants: staggerItem, className: headingClassName }, + renderHighlightedHeading(heading), )} {description && ( From b94e693397a2ff1ad2218c79db4c62ba6e1ead4d Mon Sep 17 00:00:00 2001 From: Marius Ahsmus Date: Sat, 23 May 2026 05:23:23 +0200 Subject: [PATCH 02/30] fix: remove force-dynamic --- src/app/(landing)/[locale]/layout.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/(landing)/[locale]/layout.tsx b/src/app/(landing)/[locale]/layout.tsx index f035c528..2789fb45 100644 --- a/src/app/(landing)/[locale]/layout.tsx +++ b/src/app/(landing)/[locale]/layout.tsx @@ -13,7 +13,6 @@ interface LocaleLayoutProps { } export const revalidate = 300 -export const dynamic = "force-dynamic" export default async function LocaleLayout({ children, params }: LocaleLayoutProps) { const { locale } = await params From 046e04caf06542b275ea7ce4d5afbce497fb6445 Mon Sep 17 00:00:00 2001 From: Marius Ahsmus Date: Sat, 23 May 2026 05:33:18 +0200 Subject: [PATCH 03/30] feat: remove blog sorting in page client --- src/components/blog/BlogPageClient.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/blog/BlogPageClient.tsx b/src/components/blog/BlogPageClient.tsx index 30677c82..e1cb5939 100644 --- a/src/components/blog/BlogPageClient.tsx +++ b/src/components/blog/BlogPageClient.tsx @@ -18,14 +18,6 @@ interface BlogPageClientProps { loadingLabel: string } -function sortBlogPosts(posts: BlogPostItem[]): BlogPostItem[] { - return [...posts].sort((left, right) => { - const pinOrder = Number(Boolean(right.isPinned)) - Number(Boolean(left.isPinned)) - if (pinOrder !== 0) return pinOrder - return new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime() - }) -} - function BlogCardSkeleton() { return (
@@ -85,7 +77,7 @@ export function BlogPageClient({ nextPage?: number | null } - setPosts((current) => sortBlogPosts([...current, ...(data.posts ?? [])])) + setPosts((current) => [...current, ...(data.posts ?? [])]) setHasNextPage(Boolean(data.hasNextPage)) setNextPage(data.nextPage ?? null) }) From c5f89755ee50b5eaadf163aa6f9b4e11dda633bf Mon Sep 17 00:00:00 2001 From: Marius Ahsmus Date: Sat, 23 May 2026 05:38:13 +0200 Subject: [PATCH 04/30] feat: generic functions for cms --- src/lib/cms.ts | 392 +++++++++++++++++++++---------------------------- 1 file changed, 164 insertions(+), 228 deletions(-) diff --git a/src/lib/cms.ts b/src/lib/cms.ts index 13207974..75504ce1 100644 --- a/src/lib/cms.ts +++ b/src/lib/cms.ts @@ -193,75 +193,91 @@ async function withCmsFallback(operation: string, fallback: T, run: () => Pro } } -const getLandingPageCached = cache(async (cachedSlug: string, cachedLocale: AppLocale): Promise => { - return withCmsFallback(`getLandingPage(${cachedSlug}, ${cachedLocale})`, null, async () => { - const payload = await getPayloadClient() - const result = await payload.find({ - collection: "pages", - locale: cachedLocale, - fallbackLocale: DEFAULT_LOCALE, - where: { slug: { equals: cachedSlug } }, - limit: 1, - depth: 1, - pagination: false, - }) +type CmsFindArgs = { + collection: string + locale: AppLocale + fallbackLocale?: AppLocale +} & Record + +async function cmsFind(args: CmsFindArgs): Promise { + const payload = await getPayloadClient() + const result = await payload.find(args as never) + return (result.docs as T[]) ?? [] +} + +async function cmsFindOne(operation: string, fallback: T | null, args: CmsFindArgs): Promise { + return withCmsFallback(operation, fallback, async () => { + const docs = await cmsFind(args) + return docs[0] ?? fallback + }) +} - return (result.docs[0] as Page | undefined) ?? null +async function cmsFindMany(operation: string, fallback: T[], args: CmsFindArgs): Promise { + return withCmsFallback(operation, fallback, async () => { + return cmsFind(args) + }) +} + +async function cmsFindSlugs(operation: string, locale: AppLocale, collection: string): Promise { + return cmsFindMany<{ slug: string }>(operation, [], { + collection, + locale, + fallbackLocale: DEFAULT_LOCALE, + pagination: false, + limit: 1000, + depth: 0, + select: { slug: true }, + }).then((docs) => docs.map((doc) => doc.slug).filter((slug) => slug.length > 0)) +} + +const getLandingPageCached = cache(async (cachedSlug: string, cachedLocale: AppLocale): Promise => { + return cmsFindOne(`getLandingPage(${cachedSlug}, ${cachedLocale})`, null, { + collection: "pages", + locale: cachedLocale, + fallbackLocale: DEFAULT_LOCALE, + where: { slug: { equals: cachedSlug } }, + limit: 1, + depth: 1, + pagination: false, }) }) const getNavbarItemsCached = cache(async (locale: AppLocale): Promise => { - return withCmsFallback(`getNavbarItems(${locale})`, [], async () => { - const payload = await getPayloadClient() - const result = await payload.find({ - collection: "navbarItems", - locale, - fallbackLocale: DEFAULT_LOCALE, - pagination: false, - sort: "order", - depth: 0, - }) - - return result.docs as NavbarItem[] + return cmsFindMany(`getNavbarItems(${locale})`, [], { + collection: "navbarItems", + locale, + fallbackLocale: DEFAULT_LOCALE, + pagination: false, + sort: "order", + depth: 0, }) }) const getFooterCached = cache(async (locale: AppLocale): Promise