Fixes#13527.
When upgrading to [Next.js 15.5](https://nextjs.org/blog/next-15-5) with
Payload, you might experience a runtime or build error similar to this:
```ts
Type error: Type 'typeof import("/src/app/(payload)/api/graphql/route")' does not satisfy the expected type 'RouteHandlerConfig<"/api/graphql">'.
Types of property 'OPTIONS' are incompatible.
Type '(request: Request, args: { params: Promise<{ slug: string[]; }>; }) => Promise<Response>' is not assignable to type '(request: NextRequest, context: { params: Promise<{}>; }) => void | Promise<void> | Response | Promise<Response>'.
Types of parameters 'args' and 'context' are incompatible.
Type '{ params: Promise<{}>; }' is not assignable to type '{ params: Promise<{ slug: string[]; }>; }'.
Types of property 'params' are incompatible.
Type 'Promise<{}>' is not assignable to type 'Promise<{ slug: string[]; }>'.
Property 'slug' is missing in type '{}' but required in type '{ slug: string[]; }'.
```
This is because Next.js route types are now _stricter_. Our REST handler
is nested within a catch-all `/api/[...slug]` route, so the slug param
_will_ exist in the handler—but the _same_ handler is re-used for the
`/api/graphql` OPTIONS route, which **_is not_** nested within the
`slug` param and so it **_will not_** exist as the types suggest.
---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
- https://app.asana.com/0/0/1211115021865680
---------
Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
Currently, the slug field is generated from the title field
indefinitely, even after the document has been created and the initial
slug has been assigned. This should only occur on create, however, as it
currently does, or when the user explicitly requests it.
Given that slugs often determine the URL structure of the webpage that
the document corresponds to, they should rarely change after being
published, and when they do, would require HTTP redirects, etc. to do
right in a production environment.
But this is also a problem with Live Preview which relies on a constant
iframe src. If your Live Preview URL includes the slug as a route param,
which is often the case, then changing the slug will result in a broken
connection as the queried document can no longer be found. The current
workaround is to save the document and refresh the page.
Now, the slug is only generated on initial create, or when the user
explicitly clicks the new "generate" button above the slug field. In the
future we can evaluate supporting dynamic Live Preview URLs.
Regenerating this URL on every change would put additional load on the
client as it would have to reestablish connection every time it changes,
but it should be supported still. See #13055.
Discord discussion here:
https://discord.com/channels/967097582721572934/1102950643259424828/1387737976892686346
Related: #10536
This PR consists of two separate changes. One change cannot pass CI
without the other, so both are included in this single PR.
## CI - ensure types are generated
Our website template is currently failing to build due to a type error.
This error was introduced by a change in our generated types.
Our CI did not catch this issue because it wasn't generating types /
import map before attempting to build the templates. This PR updates the
CI to generate types first.
It also updates some CI step names for improved clarity.
## Fix: type error

This fixes the type error by ensuring we consistently use the _same_
generated `TypedUser` object within payload, instead of `BaseUser`.
Previously, we sometimes used the generated-types user and sometimes the
base user, which was causing type conflicts depending on what the
generated user type was.
It also deprecates the `User` type (which was essentially just
`BaseUser`), as consumers should use `TypedUser` instead. `TypedUser`
will automatically fall back to `BaseUser` if no generated types exists,
but will accept passing it a generated-types User.
Without this change, additional properties added to the user via
generated-types may cause the user object to not be accepted by
functions that only accept a `User` instead of a `TypedUser`, which is
what failed here.
## Templates: re-generate templates to update generated types
---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
- https://app.asana.com/0/0/1210668927737258
Adds full session functionality into Payload's existing local
authentication strategy.
It's enabled by default, because this is a more secure pattern that we
should enforce. However, we have provided an opt-out pattern for those
that want to stick to stateless JWT authentication by passing
`collectionConfig.auth.useSessions: false`.
Todo:
- [x] @jessrynkar to update the Next.js server functions for refresh and
logout to support these new features
- [x] @jessrynkar resolve build errors
---------
Co-authored-by: Elliot DeNolf <denolfe@gmail.com>
Co-authored-by: Jessica Chowdhury <jessica@trbl.design>
Co-authored-by: Jarrod Flesch <30633324+JarrodMFlesch@users.noreply.github.com>
Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
This PR adds int tests with vitest and e2e tests with playwright
directly into our templates.
The following are also updated:
- bumps core turbo to 2.5.4 in monorepo
- blank and website templates moved up to be part of the monorepo
workspace
- this means we now have thes templates filtered out in pnpm commands in
package.json
- they will now by default use workspace packages which we can use for
manual testing and int and e2e tests
- note that turbo doesnt work with these for dev in monorepo context
- CPA script will fetch latest version and then replace `workspace:*` or
the pinned version in the package.json before installation
- blank template no longer uses _template as a base, this is to simplify
management for workspace
- updated the generate template variations script
Fixes https://github.com/payloadcms/payload/issues/9449
Previously, search sync with categories didn't work and additionally
caused problems with Postgres. Additionally, ensures that when doing
synchronization, all the categories are populated, since we don't always
have populated data inside hooks.
### What?
Fixes#12171
### Why?
Previously, the ImageMedia component was not properly handling URL
formatting when a serverURL was configured in Payload. This caused
images to fail to load when using a custom serverURL. By extracting the
URL handling logic into a separate utility function, we ensure
consistent URL processing across both image and video components.
### How?
1. Created a new utility function getMediaUrl in
`src/utilities/getMediaUrl.ts` that:
- Properly checks for HTTP/HTTPS protocols
- Handles null or undefined URL values
- Supports cache tags to prevent caching issues
- Uses `getClientSideURL()` for relative paths
2. Updated the ImageMedia component to use this utility function instead
of inline URL processing logic
3. Updated the VideoMedia component to also use the same utility
function for consistency
### What?
The default value is hardcoded instead of respecting the value filled in
the form setting
Fixes #
pass it down from props
Co-authored-by: Pan <kpkong@hk01.com>
Sometimes I need to add some classes to the `picture` tag of Media
component. in this case I need to do this:
```
<Media
resource={content.image}
className="w-full h-full [&>picture]:w-full" // <<< follow this
imgClassName="w-full h-full object-cover"
/>
```
So I added an additional props `pictureClassName` for the picture tag.
Now I can do this:
```
<Media
resource={content.image}
className="w-full h-full"
pictureClassName="w-full h-full" // <<< follow this
imgClassName="w-full h-full object-cover"
/>
```
NOTE: I've encountered situations where I needed to add classes to the
`picture` tag, not just for `w-full h-full`. To handle this, I had to
update the Media component. I believe this would be a valuable
improvement to the Media component.
Close#11274
### Why this PR?
I've created a custom phone number input block for my form builder,
including validation. However, the component on the frontend only
displays the generic message "This field is required," even when
formState.errors contains specific error messages. This is not the
expected behavior. I need the component to display the error messages
from formState.errors.
### Description
This pull request includes changes to improve error handling in various
form components by passing the `name` prop to the `Error` component and
updating the `Error` component to display specific error messages.
#### Error handling improvements:
*
[`templates/website/src/blocks/Form/Error/index.tsx`](diffhunk://#diff-a97a4b2b87ff1a02431d11ab00f4e0ead5d11819f45dac120b9502ace520196fR1-R14):
Updated the `Error` component to accept a `name` prop and use
`useFormContext` to display specific error messages.
#### Form component updates:
*
[`templates/website/src/blocks/Form/Checkbox/index.tsx`](diffhunk://#diff-4f0ad9596965f1e3b2f6356943d1d34009a742502bc8ab8d438ce98593fdef4aL42-R42):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/Country/index.tsx`](diffhunk://#diff-3abd97c2bfe7ce2a1809e6eaac68e6c02078514308f964b1792f7a1af2df92a7L62-R62):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/Email/index.tsx`](diffhunk://#diff-f1be3cf1e7c1fa9b543ed8f56a3655e601fdb399d31ede1d099a37004a1861bfL35-R35):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/Number/index.tsx`](diffhunk://#diff-72e5bd63eda769bce077e87bc614cb338211600580ad38ba86a7f066a35212a5L33-R33):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/Select/index.tsx`](diffhunk://#diff-69d52ba3bb01fc0ce4428f5b76ab48a86c448dceaf36390edbcf345f0b15c34eL60-R60):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/State/index.tsx`](diffhunk://#diff-c0eb5a8c64b6384a44e19556556921bff4c89ed3a8d5a1d2e46ce493178587caL61-R61):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/Text/index.tsx`](diffhunk://#diff-9d32d5b3132729534809280d97d8a0952e96270f434b5d57a32a2d4981a36384L29-R29):
Modified to pass the `name` prop to the `Error` component.
*
[`templates/website/src/blocks/Form/Textarea/index.tsx`](diffhunk://#diff-d25c7cb831ee04c195983c1a88718bdcec8f1dc34c3e5237875678eb8194994dL37-R37):
Modified to pass the `name` prop to the `Error` component.
The Payload Admin Bar is now maintained in core and released under the
`@payloadcms` scope thanks to #3684. All templates and examples that
rely on this package now install from here and have been migrated
accordingly.
- Ensures website templates build without eslint errors
- Upgrades all templates from Next.js 15.1.5 to 15.2.0
- Bumps all payload versions, updates all lockfiles to reference latest payload versions. The blank template was still installing 3.17.1 and the website template was installing 3.18.0
- Simplifies defaultLexical.ts
Our previous `RichTextWithoutBlocks` import alias was confusing - this PR changes it to `ConvertRichText`. This should make it clear that that's the imported RichText component that performs the editor state => JSX conversion
Adds a dedicated "Custom Components" section to the docs.
As users become familiar with building custom components, not all areas
that support customization are well documented. Not only this, but the
current pattern does not allow for deep elaboration on these concepts
without their pages growing to an unmanageable size. Custom components
in general is a large enough topic to merit a standalone section with
subpages. This change will make navigation much more intuitive, help
keep page size down, and provide room to document every single available
custom component with snippets to show exactly how they are typed, etc.
This is a substantial change to the docs, here is the overview:
- The "Admin > Customizing Components" doc is now located at "Custom
Components > overview"
- The "Admin > Views" doc is now located at "Custom Components > Custom
Views"
- There is a new "Custom Components > Edit View" doc
- There is a new "Custom Components > List View" doc
- The information about root components within the "Admin > Customizing
Components" doc has been moved to a new "Custom Components > Root
Components" doc
- The information about custom providers within the "Admin > Customizing
Components" doc has been moved to a new "Custom Components > Custom
Providers" doc
Similar to the goals of #10743, #10742, and #10741.
Fixes#10872 and initial scaffolding for #10353.
Dependent on #11126.
This change will require the following redirects to be set up:
- `/docs/admin/hooks` → `/docs/admin/react-hooks`
- `/docs/admin/components` → `/docs/custom-components/overview`
- `/docs/admin/views` → `/docs/custom-components/views`
The `Media` component has an optional property `resource` so we can skip
that property. As in payload `required: false` types are generated like
`media?: Media | string | null`, it also makes sense to allow `null` as
a `resource` value.
Fixes https://github.com/payloadcms/payload/issues/11200
🤖 Automated bump of templates for v3.23.0
Triggered by user: @denolfe
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
We now properly allow relative live preview URLs which is handy if
you're deploying on a platform like Vercel and do not know what the
preview domain is going to end up being at build time.
This PR also removes some problematic code in the website template which
hard-codes the protocol to `https://` in production even if you're
running locally.
Fixes#11070
`JSON.parse(JSON.stringify().replace())` is easy to make mistakes with and since we have TypeScript data objects already for the data we're seeding it's pretty easy to just factor these as functions, making their dependencies explicit.
Similar to #10876. There were a number of things wrong or in need of
improvement with the Draft Preview implementation of the Website
Template, namely:
- The preview secret was missing entirely, with pointless logic was
written to throw an error if it missing in the search params as opposed
to not matching the environment secret. This will ensure that only admin
users, not _any_ user, can enter into preview mode.
- The preview endpoint was unnecessarily querying the database for a
matching document as opposed to letting the underlying page itself 404
as needed, and it was also throwing an inaccurate error message. The
preview route already checks that the path is relative, so there is no
security risk of redirecting to another domain.
- The `/next/exit-preview` route was duplicated twice.
- The logic to format search params in the preview URL was unnecessarily
complex.
* set font-size to unset
* set font-weight to unset
### What?
Change CSS values in global.css files in 3 examples
### Why?
Apparently, the CSS value of `auto` does not actually exist in CSS for
`font-size` and `font-weight`
[mdn](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#syntax)
.
[Stylelint](https://stylelint.io/user-guide/rules/declaration-property-value-no-unknown/)
errors made me aware of this. That rule's description is not specific to
`font-size` and `font-weight`.
This is how it looked in the terminal:
```
src/app/(frontend)/globals.css
12:18 ✖ Unexpected unknown value "auto" for property "font-weight" declaration-property-value-no-unknown
13:16 ✖ Unexpected unknown value "auto" for property "font-size" declaration-property-value-no-unknown
```
### Fixes:
Change `auto` to `unset` since it uses `initial` styles unless the
heading CSS values have been changed by a parent html tag. I'm guessing
this was reset due to tailwind interrupting this somehow.
Fixes: https://github.com/payloadcms/payload/issues/10787
The underlying problem is that there are types in the form builder
plugin that are unnecessarily `any` or `unknown`.
Here in the website template this was being circumvented with a function
that was not really needed (buildInitialFormState), and with new unknown
types (Value, Property and Data).
Since create-payload-app fetches from the latest commit instead of the
latest release, it is necessary to first merge
https://github.com/payloadcms/payload/pull/10789, and once the next
release is done this PR can be merged.
* introduce AbortController to the event listeners in useClickableCard
* in an attempt to avoid ugly boolean check
* suggested pattern from
https://kettanaito.com/blog/dont-sleep-on-abort-controller
<!--
Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.
Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.
The following items will ensure that your PR is handled as smoothly as
possible:
- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change
### What?
Add AbortController to event listeners in useClickableCard.
### Why?
Following Theo's [video](https://www.youtube.com/watch?v=2sdXSczmvNc)
about the [blog
post](https://kettanaito.com/blog/dont-sleep-on-abort-controller) about
AbortController I came across a bit of code in examples that looked a
bit ugly and thought the AbortController could simplify it a bit
(especially the checks for the DOM node in the removal part).
### How?
Just re-writing the code in a different way. Though, I admit I'm not
wholly sure where the Cards are being used and for what purpose so I
haven't checked that there is no difference to the behaviour of the
code.
Fixes #
Not so much a fix but a different way to write the removal of event
listeners.
-->
Previously images would not be revalidated if they were cropped or
changed in another ways.
Now if the image is updated, they will also be updated on the frontend
whenever a post is revalidated.
Fixes the utilities alias used by shadcn to a specific file renamed to
`ui.ts` from `cn.ts` since there may be other utilities installed by
shadcn depending on the components the user installs.
Co-Authored-By: Q.Tran <quan.tran@metro.digital>
🤖 Automated bump of templates for v3.16.0
Triggered by user: @denolfe
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Fixes#10325. Since React 19, refs can now be passed directly through
props without the need for `React.forwardRef`. This greatly simplifies
components types and overall syntax.
fix#10197
The template was missing defining internalDocToHref.
This callback is necessary because Payload does not know which URLs each
document will be displayed on.
Fixes#10070. Adding new blocks or array rows can randomly get stuck
within an infinite loading state. This was because the abort controllers
responsible for disregarding duplicate `onChange` and `onSave` events
was not properly resetting its refs across invocations. This caused
subsequent event handlers to incorrectly abort themselves, leading to
unresolved requests and a `null` form state. Similarly, the cleanup
effects responsible for aborting these requests on component unmount
were also referencing its `current` property directly off the refs,
which can possible be stale if not first set as a variable outside the
return function.
This PR also carries over some missing `onSave` logic from the default
edit view into the live preview view. In the future the logic between
these two views should be standardized, as they're nearly identical but
often become out of sync. This can likely be done through the use of
reusable hooks, such as `useOnSave`, `useOnChange`, etc. Same with the
document locking functionality which is complex and deeply integrated
into each of these views.
I noticed that payload.secret was getting logged via console.log, adding
a significant security risk.
Removed the console.log statements from three preview/route.ts files.
This PR fixes an issue in the hero banner of website templates where
`priority` was passed to `ImageMedia` component but was incompatible with
NextImage `loading="lazy"`, causing error. The fix is to add a ternary
condition to check if `priority` prop is passed before setting `loading.