diff --git a/src/app/(frontend)/projects/[slug]/page.tsx b/src/app/(frontend)/projects/[slug]/page.tsx
new file mode 100644
index 0000000..5c32ab8
--- /dev/null
+++ b/src/app/(frontend)/projects/[slug]/page.tsx
@@ -0,0 +1,23 @@
+import { notFound } from 'next/navigation'
+import { getProjectBySlug, listAllProjectSlugs } from '@/lib/projects'
+import { Render } from '@/components/lexical/Render'
+
+export const revalidate = 60
+
+export async function generateStaticParams() {
+ return (await listAllProjectSlugs()).map((slug) => ({ slug }))
+}
+
+export default async function ProjectPage({ params }: { params: Promise<{ slug: string }> }) {
+ const { slug } = await params
+ const project = await getProjectBySlug(slug)
+ if (!project) notFound()
+ return (
+
+ {project.title}
+
+
+
+
+ )
+}
diff --git a/src/app/(frontend)/projects/page.tsx b/src/app/(frontend)/projects/page.tsx
new file mode 100644
index 0000000..eed241d
--- /dev/null
+++ b/src/app/(frontend)/projects/page.tsx
@@ -0,0 +1,20 @@
+import { listProjects } from '@/lib/projects'
+import { ProjectPreview } from '@/components/ProjectPreview'
+
+export const revalidate = 60
+
+export default async function ProjectsIndex() {
+ const r = await listProjects()
+ return (
+
+
Projects
+
+ {r.docs.map((p) => (
+ -
+
+
+ ))}
+
+
+ )
+}
diff --git a/src/components/ProjectPreview.tsx b/src/components/ProjectPreview.tsx
new file mode 100644
index 0000000..5941554
--- /dev/null
+++ b/src/components/ProjectPreview.tsx
@@ -0,0 +1,40 @@
+import Link from 'next/link'
+import type { Project } from '@/payload-types'
+
+interface ProjectPreviewProps {
+ project: Project
+ className?: string
+ headingLevel?: 'h2' | 'h3'
+}
+
+export function ProjectPreview({
+ project,
+ className,
+ headingLevel: TitleTag = 'h2',
+}: ProjectPreviewProps) {
+ const { title, slug, description } = project
+
+ return (
+
+
+
+ {title}
+
+ {description && (
+
{description}
+ )}
+
+
+ →
+
+
+ )
+}
diff --git a/src/lib/projects.ts b/src/lib/projects.ts
new file mode 100644
index 0000000..49537a3
--- /dev/null
+++ b/src/lib/projects.ts
@@ -0,0 +1,30 @@
+import { getPayloadInstance } from './payload'
+import type { Project } from '@/payload-types'
+
+export async function listProjects() {
+ const payload = await getPayloadInstance()
+ return payload.find({
+ collection: 'projects',
+ where: { _status: { equals: 'published' } },
+ sort: '-publishDate',
+ limit: 0,
+ pagination: false,
+ depth: 1,
+ })
+}
+
+export async function getProjectBySlug(slug: string): Promise {
+ const payload = await getPayloadInstance()
+ const r = await payload.find({
+ collection: 'projects',
+ where: { slug: { equals: slug } },
+ depth: 2,
+ limit: 1,
+ })
+ return r.docs[0]
+}
+
+export async function listAllProjectSlugs(): Promise {
+ const r = await listProjects()
+ return r.docs.map((d) => d.slug)
+}