-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Description
Link to reproduction
No response
Environment Info
Payload: 3.0.0-beta.113
Node.js: 22.9.0
Next.js: 15.0.0-canary.173
Describe the Bug
Despite implementing the suggested changes from issue #8463, the build process continues to fail when using Payload CMS with Next.js App Router. The problem seems to be related to how params is being passed to page components and metadata generation functions. I suspect that the handling of the locale parameter might be contributing to this issue.
When trying to run the build, I get this error ->
Type error: Type '{ params: { locale: string; }; }' does not satisfy the constraint 'PageProps'. Types of property 'params' are incompatible. Type '{ locale: string; }' is missing the following properties from type 'Promise<SegmentParams>': then, catch, finally, [Symbol.toStringTag]
Here is my localized [slug]-page handling the pages created via Payload CMS.
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { PayloadRedirects } from '@/components/PayloadRedirects'
import configPromise from '@payload-config'
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { draftMode } from 'next/headers'
import React, { cache } from 'react'
import type { Page as PageType } from 'src/payload-types.ts'
import { RenderBlocks } from '@/blocks/RenderBlocks'
import { generateMeta } from '@/utilities/generateMeta'
type Args = {
params: Promise<{
slug?: string
locale: string
}>
}
export default async function Page({ params }: Args) {
const { slug = 'home', locale } = await params
const url = `/${locale}/${slug}`
const { isEnabled: isDraftMode } = await draftMode()
let page: PageType | null
page = await queryPageBySlug({
slug,
locale,
isDraftMode,
})
if (!page || (locale === 'en' && page._status !== 'published' && !isDraftMode)) {
return notFound()
}
return (
<article className="container pb-24">
<PayloadRedirects disableNotFound url={url} />
<RenderBlocks blocks={page.layout} />
</article>
)
}
export async function generateMetadata({ params }: Args): Promise<Metadata> {
const { slug = 'home', locale } = await params
const { isEnabled: isDraftMode } = await draftMode()
const page = await queryPageBySlug({
slug,
locale,
isDraftMode,
})
if (!page || (locale === 'en' && page._status !== 'published' && !isDraftMode)) {
return {}
}
return generateMeta({ doc: page })
}
const queryPageBySlug = cache(
async ({ slug, locale, isDraftMode }: { slug: string; locale: string; isDraftMode: boolean }) => {
const payload = await getPayloadHMR({ config: configPromise })
const page = await payload.find({
collection: 'pages',
where: {
slug: {
equals: slug,
},
...(locale === 'en' && !isDraftMode ? { _status: { equals: 'published' } } : {}),
},
limit: 1,
depth: 2,
locale: locale as 'en' | 'de',
draft: isDraftMode,
})
return page.docs[0]
},
)
Reproduction Steps
-
Set up a Next.js project with App Router and Payload CMS integration.
-
Implement internationalization (i18n) in your Next.js app with Next-Intl.
-
Create a dynamic route file for handling pages created via Payload CMS, e.g.,
app/[locale]/(frontend)[slug]/page.tsx. -
In this file, implement the page component and metadata generation as follows:
import type { Metadata } from 'next' import { notFound } from 'next/navigation' import { PayloadRedirects } from '@/components/PayloadRedirects' import configPromise from '@payload-config' import { getPayloadHMR } from '@payloadcms/next/utilities' import { draftMode } from 'next/headers' import React, { cache } from 'react' import type { Page as PageType } from 'src/payload-types.ts' import { RenderBlocks } from '@/blocks/RenderBlocks' import { generateMeta } from '@/utilities/generateMeta' type Args = { params: Promise<{ slug?: string locale: string }> } export default async function Page({ params }: Args) { const { slug = 'home', locale } = await params // ... rest of the component } export async function generateMetadata({ params }: Args): Promise<Metadata> { const { slug = 'home', locale } = await params // ... rest of the function } // ... queryPageBySlug function
-
Ensure that your
next.config.jsis properly configured for i18n and Payload CMS.
import { withPayload } from '@payloadcms/next/withPayload'
import createNextIntlPlugin from 'next-intl/plugin'
import { withSentryConfig } from '@sentry/nextjs'
import redirects from './redirects.js'
const withNextIntl = createNextIntlPlugin()
const NEXT_PUBLIC_SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:3000'
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
use: ['@svgr/webpack'],
})
return config
},
images: {
remotePatterns: [
...[NEXT_PUBLIC_SERVER_URL].map((item) => {
const url = new URL(item)
return {
hostname: url.hostname,
protocol: url.protocol.replace(':', ''),
}
}),
],
},
reactStrictMode: true,
redirects,
}
// Combine withNextIntl, withPayload, and withSentryConfig
const combinedConfig = withSentryConfig(withNextIntl(withPayload(nextConfig)), {
// Sentry config options
org: 'organization-name',
project: 'project-name',
silent: !process.env.CI,
widenClientFileUpload: true,
reactComponentAnnotation: {
enabled: true,
},
tunnelRoute: '/monitoring',
hideSourceMaps: true,
disableLogger: true,
automaticVercelMonitors: true,
})
export default combinedConfig- Run
next buildto start the build process. It fails with this error ->
Type error: Type '{ params: { locale: string; }; }' does not satisfy the constraint 'PageProps'.
Types of property 'params' are incompatible.
Type '{ locale: string; }' is missing the following properties from type 'Promise<SegmentParams>': then, catch, finally, [Symbol.toStringTag]
Adapters and Plugins
No response