Adding support for Payload in your Nx workspace.
- Prerequisites
- Installation
- Usage
- Developer Experience (DX)
- You don't have an Nx workspace?
- Plugin Generators
- Migrate from Payload v2 to v3
- Versions Compatibility
- You have already created an Nx workspace
- Node 20+
- Docker
The commands in this readme assume that Nx is installed globally.
nx [...]
If you prefer not to, you can use your preferred package manager to prefix the commands like this example for npm
.
npx nx [...]
# or
npm run nx [...]
Important
This documentation is aimed for a Payload v3 setup.
To install Payload v2 you should use plugin version 1.x.
Though it's possible to have applications using Payload v2 and v3 in the same workspace, it's not recommended. Payload v2 supports React 18 and v3 has moved to React 19. But with individual package.json
files for the applications and some Dockerfiles sed
magic it's possible to make it work.
nx add @cdwr/nx-payload
The plugin automatically generates Payload tasks for projects that has a payload.config.ts
file somewhere in the project. The default location is in {projectRoot}/src
.
gen
payload
payload-graphql
Tip
A couple of targets to improve Developer Experience (DX) are also generated:
dx:mongodb
dx:postgres
dx:start
dx:stop
Plugin configuration is added to nx.json
by default.
{
"plugins": [
{
"plugin": "@cdwr/nx-payload/plugin",
"options": {
"generateTargetName": "gen",
"payloadTargetName": "payload",
"payloadGraphqlTargetName": "payload-graphql",
"dxMongodbTargetName": "dx:mongodb",
"dxPostgresTargetName": "dx:postgres",
"dxStartTargetName": "dx:start",
"dxStopTargetName": "dx:stop"
}
}
]
}
To disable automatic targets generation and write explicit targets to project.json
, use one of these two options:
- Set
useInferencePlugins
innx.json
tofalse
- Set environment variable
NX_ADD_PLUGINS
tofalse
nx g @cdwr/nx-payload:app
Payload has official support for database adapters MongoDB, Postgres and SQLite.
Tip
Supabase is set up using the Postgres adapter
Changing the adapter for a generated application must be done manually in payload.config.ts
.
Important
We don't want to infer opinionated complexity into the Payload configuration. A new application is just a working template that you will customize and evolve to your needs.
Fortunately, changing the database is straightforward, and only a few parts need to be replaced.
// MongoDB @ payload.config.ts
import { mongooseAdapter } from '@payloadcms/db-mongodb';
export default buildConfig({
db: mongooseAdapter({
url: process.env.DATABASE_URI
})
});
// Postgres/Supabase @ payload.config.ts
import { postgresAdapter } from '@payloadcms/db-postgres';
export default buildConfig({
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URI
}
})
});
Tip
More information can be found on the official Payload Database page.
The application come with a set of opinionatedtargets to improve developer experience. These targets are prefixed with dx:
are optional to use.
Tip
Display all the targets with extensive details for an application
nx show project [app-name]
This is the quickest way to get Payload up and running in no time.
Using docker compose, both MongoDB and Postgres are started in each container, as well as the Payload application.
nx dx:start [app-name]
Open your browser and navigate to http://localhost:3000 to setup your first user.
Shutdown database and Payload containers.
nx dx:stop [app-name]
Database volumes are persistent, hence all data is available on next launch.
You can also start the preferred database first, to be properly initialized before Payload is served.
Run MongoDB in Docker
nx dx:mongodb [app-name]
Run Postgres in Docker
nx dx:postgres [app-name]
Supabase has its own powerful toolset running local dev with CLI
npx supabase init
npx supabase start
Edit DATABASE_URI
in .env.local
when needed.
Payload application is served in watch mode.
Note
The configured database must have been started, see local database
nx dev [app-name]
Open your browser and navigate to http://localhost:3000.
All commands available from Payload can be used for the application via targets payload
and payload-graphql
.
nx payload [app-name] [payload-command]
This is specially useful for managing migrations, for example to check database migration status.
nx payload [app-name] migrate:status
To provide a better developer experience for client development, the plugin can generate TypeScript types and GraphQL schema files from the Payload configuration.
Important
GraphQL schema will not be generated if graphQL.disable
is set to true
in payload.config.ts
nx gen [app-name]
The generated files are written to the generated
folder.
The types can be distributed to the client developer manually or saved to a shared library in the monorepo.
Note
The gen
target is actually an alias for the following commands.
nx payload [app-name] generate:types
nx payload-graphql [app-name] generate:schema
Using Postgres in development mode enables automatic database synchronization with the Payload collections. But when starting in production mode it's turned off and the database is expected to have been setup with the collections. So when Postgres is started without a database, Payload will encounter errors.
The solution is to have an initial migration ready for Payload to load during startup.
Make sure Postgres is running. Start Payload in development mode to setup your database with the collections.
nx dev [app-name]
Create a migration.
nx payload [app-name] migrate:create
Now Payload will run migrations automatically when starting in production mode.
Important
The property db.prodMigrations
in payload.config.ts
must be set for this to work.
Just use the plugin sibling to get started from scratch.
See create-nx-payload
for more details.
Initialize the @cdwr/nx-payload
plugin.
No options.
Alias: app
Generate a Payload application powered by Next.js.
Option | Type | Required | Default | Description |
---|---|---|---|---|
name |
string | ✅ | The name of the application. | |
directory |
string | ✅ | The path of the application files. | |
database |
string | mongodb |
Preferred database to setup [mongodb , postgres ]. |
|
tags |
string | '' |
Comma separated tags. | |
e2eTestRunner |
string | none |
The preferred e2e test runner [ playwright , none ]. |
|
linter |
string | eslint |
The tool to use for running lint checks. | |
unitTestRunner |
string | jest |
The preferred unit test runner [ jest , none ]. |
💡
name
can also be provided as the first argument (used in the examples in this readme)
Most of the setup is the same, but there are some breaking changes that you need to be aware of. Besides that, follow the type errors to update the code.
- Nx must have version
20.4.2
or higher. - React must have version
19.0.0
or higher. - Install
@nx/next
plugin. - Install
@nx/eslint
plugin.- Convert to flat file configuration.
- Use
eslint.config.mjs
files.
- Install
graphql
package.
Payload now use a common version for its packages.
Install new packages:
@payloadcms/next
@payloadcms/graphql
(dev dependency)
Update to latest:
payload
@payloadcms/db-mongodb
@payloadcms/db-postgres
@payloadcms/richtext-lexical
Remove deprecated packages:
@payloadcms/bundler-webpack
@payloadcms/richtext-slate
@nx/express
(used elsewhere?)
Later versions of Nx or Payload might work as well, but the versions below have been used during tests.
Plugin | Nx | Payload | React | Next.js |
---|---|---|---|---|
^2.0.0 |
^20.4.2 |
^3.0.0 |
^19.0.0 |
^15.0.0 |
^1.0.0 |
20.x |
^2.30.3 |
^18.0.0 |
- |
^0.11.0 |
20.x |
^2.30.3 |
^18.0.0 |
- |
^0.10.0 |
19.x |
^2.8.2 |
- | - |
^0.9.5 |
^19.5.7 |
^2.8.2 |
- | - |
^0.9.0 |
^19.0.2 |
^2.8.2 |
- | - |
^0.8.0 |
^18.3.4 |
^2.8.2 |
- | - |
^0.7.0 |
~18.2.2 |
^2.8.2 |
- | - |
^0.6.0 |
~18.1.1 |
^2.8.2 |
- | - |
^0.5.0 |
~18.0.3 |
^2.8.2 |
- | - |
^0.1.0 |
^17.0.0 |
^2.5.0 |
- | - |