

In this third part of our Payload NextJS tutorial series, we will dive into the essential configurations needed for your project. We'll explore how to set up environment variables dynamically, adjust your Webpack configuration, and ensure smooth authentication between your front end and back end.
This is the written guide for our Comprehensive Payload NextJS Setup Guide Series (Part 3). You can find the full length video here:
https://www.youtube.com/watch?v=lmeOiOtvdT8
Environment variables are essential for configuring your application without hardcoding values directly into your code. They allow you to manage settings like API keys, database URLs, and server ports. In a Payload NextJS project, these variables can make your application more flexible and easier to manage across different environments such as development, testing, and production.
In this section, we will focus on how to set up and utilize environment variables effectively, ensuring that your application behaves correctly in various scenarios.
To enhance the functionality of your Payload NextJS application, you may need to add new environment variables. Here’s a simple way to do that:
payload_public_external_server_url to http://localhost:4000.The payload_public_external_server_url variable is crucial as it replaces the hardcoded server URL in your configuration. This allows the Payload admin panel to access the correct server URL dynamically.
When using this variable, it’s important to prefix it with payload public. This is similar to how environment variables are treated in Next.js, where front-end accessible variables are prefixed with next public. This distinction helps maintain security while still providing necessary information to your frontend.

Static ports can be problematic, especially when deploying your application in different environments. To avoid issues, it’s essential to set up a dynamic port configuration.
In your server.ts file, replace any hardcoded port number with process.env.port. This will allow your application to utilize the port defined in your environment variables, making it adaptable for various deployment scenarios.
If you’re not utilizing GraphQL in your application, it’s best to disable it entirely. This can be done by modifying the GraphQL attributes in your Payload configuration.
Simply remove all existing settings and add the line:
disable: true
This will ensure that GraphQL is not included in your application, reducing unnecessary overhead.
When starting with a new Payload project, you typically have a default collection setup. The primary collection is often users, which is critical for authentication. You can manage this collection by adjusting its settings to fit your needs.
For example, if you want to use this collection with a separate frontend, you’ll need to modify the authentication settings. Specifically, replace the auth: true attribute with a cookie configuration object that specifies secure and same-site settings based on your environment.
process.env.payload_env !== 'development'.process.env.payload_env === 'testing' for a value of none.This configuration ensures that your application can handle cookies correctly, enhancing security while maintaining functionality across different environments.

To enable cross-origin requests from your frontend, you’ll need to implement a whitelist for origins. This is particularly important when your frontend and backend are served from different domains.
In your Payload configuration, add the following:
cors: process.env.whitelist_origins.split(',')
This will allow you to specify multiple origins, enhancing security while still enabling necessary API calls from your frontend.
Setting up cookies correctly is crucial, especially when dealing with authentication across different environments. To ensure that your Payload NextJS application can handle cookies securely, we need to adjust the authentication settings of your main collection.
Instead of using a simple auth: true attribute, we will replace it with a cookie configuration object. This allows for more granular control over cookie behavior:
cookies: {
secure: process.env.payload_env !== 'development',
sameSite: process.env.payload_env === 'testing' ? 'none' : 'lax'
}The secure setting ensures that cookies are only transmitted over HTTPS, which is necessary in production but can be disabled during development on localhost. The sameSite attribute helps mitigate CSRF attacks by controlling how cookies are sent with cross-origin requests.

Dynamic settings based on the environment are essential for maintaining a secure and functional application. In development, we often work under less secure conditions (e.g., HTTP), so disabling secure cookies allows for smoother testing. Conversely, in production, we enforce secure cookies to protect user data.
By using the payload_env variable, we can easily switch between these configurations without needing to change the code directly.
Cross-Origin Resource Sharing (CORS) is a critical aspect of web security that allows or restricts resources on a web page to be requested from another domain. In a typical setup with Payload NextJS, you will need to specify which origins are permitted to interact with your backend.
To set this up, you will add an environment variable called whitelist_origins to your configuration. This will contain a comma-separated list of origins that your backend should allow:
cors: process.env.whitelist_origins ? process.env.whitelist_origins.split(',') : []
This configuration ensures that if no origins are specified, an empty array is returned, preventing any unwanted access.

In addition to the CORS settings, you should also configure CSRF protection to safeguard against cross-site request forgery attacks. This is done similarly by specifying the same origins for CSRF requests:
csrf: process.env.whitelist_origins ? process.env.whitelist_origins.split(',') : []
By aligning your CORS and CSRF settings, you ensure a consistent security posture for your application.
To streamline the deployment process, particularly on platforms like Railway, it's important to make a couple of adjustments to your package.json file. First, replace the npm run serve command with npm run start. This change simplifies the deployment process as Railway automatically runs npm run build followed by npm run start.
Next, extend the copy_files script to include additional file types that might be necessary for your build:
copy_files: {
ejs: 'src/**/*.ejs',
json: 'src/**/*.json',
// Add other file types as needed
}This ensures that all necessary files are included in the build, preventing potential runtime errors due to missing assets.
When working with server-only modules like the fs module, it's critical to configure Webpack to prevent these from being included in the client-side bundle. This can be achieved by creating a mock for the module that simply exports an empty function.
First, create a new folder called mocks in your source directory, and add a file named emptyFunction.js:
export default function() {}
Next, in your Payload configuration under the admin attribute, import this mock and configure Webpack:
webpack: (config) => {
config.resolve.alias['fs'] = path.resolve(__dirname, 'mocks', 'emptyFunction.js');
return config;
}This setup effectively tells Webpack to ignore the fs module during the bundling process, preventing errors when your application runs in the browser.
In this tutorial, we've covered essential configurations for your Payload NextJS project, including cookie management for authentication, CORS settings, package adjustments for deployment, and Webpack configurations for server-only modules. By implementing these practices, you can ensure a more secure and efficient application.
As you proceed, consider exploring additional features such as file uploads using an S3 bucket and user management through the Payload admin panel. These enhancements will further strengthen your application’s capabilities.
payload_env variable?The payload_env variable helps distinguish between different environments (development, testing, production) and allows for dynamic configuration of settings like cookies and CORS.
Ensure that your cookie settings allow for cross-origin requests and that you have whitelisted the frontend origins in your CORS configuration.
Server-only modules like fs cannot be executed in a browser environment. Mocking them prevents Webpack from including them in the client-side bundle, avoiding runtime errors.
Yes, you can use TypeScript for your Payload project. However, ensure that your main configuration files remain in TypeScript to leverage type safety.