Production Guides & Recipes
Managed Unicode Slugs
Section titled “Managed Unicode Slugs”The slugField factory generates URL-friendly slugs while preserving non-Latin scripts (such as Persian and Arabic):
import { slugField } from "@nexload-sdk/payload-fields";
const fields = [ { name: "title", type: "text", required: true }, ...slugField({ source: "title", overrides: { admin: { position: "sidebar", description: "Auto-generated from title. Unlock to manually edit.", }, }, }),];Slug Locking Mechanism
Section titled “Slug Locking Mechanism”- When a document is first created,
slugLockdefaults totrue. - Editing the
titlefield automatically updatesslug. - Once the user clicks the lock icon to lock the slug, future changes to
titlewill never alterslug. - This prevents unintentional breakage of indexed search engine URLs.
Jalali (Persian Solar) Datepicker
Section titled “Jalali (Persian Solar) Datepicker”Store standard ISO datetimes while providing a rich Persian Solar calendar widget in Payload Admin:
import { jalaliDateField } from "@nexload-sdk/payload-fields";
const fields = [ jalaliDateField({ name: "eventDate", pickerAppearance: "dayAndTime", // Options: "dayOnly" | "dayAndTime" overrides: { required: true, admin: { description: "Select date in Iranian Solar (Shamsi) calendar.", }, }, }),];Date Storage Guarantees
Section titled “Date Storage Guarantees”- The database always stores standard UTC ISO 8601 strings (e.g.
2026-07-24T12:00:00.000Z). - Date ranges, GraphQL queries, and database sorting (
sort: "-eventDate") operate natively without custom database adapters.
Safe-Integer Money Fields
Section titled “Safe-Integer Money Fields”Prevent JavaScript floating point inaccuracies (e.g. 0.1 + 0.2 === 0.30000000000000004) by storing currency in integer minor units:
import { moneyField } from "@nexload-sdk/payload-fields";
const fields = [ moneyField({ name: "unitPrice", currency: "USD", // Stored in cents (e.g. $19.99 is stored as 1999) minMinorUnits: 0, maxMinorUnits: 10_000_000, overrides: { required: true, }, }), moneyField({ name: "rialPrice", currency: "IRR", // Stored in Rials minMinorUnits: 0, }),];Read & Write Contract
Section titled “Read & Write Contract”- Payload Admin UI: The user types human-readable amounts (e.g.
19.99). The custom Admin component formats the input with thousands separators. - REST / GraphQL / Local API: Callers must always send and receive the raw integer minor unit (
1999).
Custom Server-Side Slug Generators
Section titled “Custom Server-Side Slug Generators”When slug generation requires asynchronous database checks or business rules:
import { payloadFieldsPlugin, slugField } from "@nexload-sdk/payload-fields";import { buildConfig } from "payload";
export default buildConfig({ collections: [ { slug: "posts", fields: [ { name: "title", type: "text", required: true }, ...slugField({ source: "title", generator: "postSlug" }), ], }, ], plugins: [ payloadFieldsPlugin({ // Protect the generation endpoint generateSlugAccess: ({ req }) => Boolean(req.user), slugGenerators: { postSlug: async ({ sourceValue, req }) => { const baseSlug = sourceValue.trim().toLowerCase().replace(/\s+/g, "-"); // Check for existing slug collision const count = await req.payload.count({ collection: "posts", where: { slug: { equals: baseSlug } }, });
return count.totalDocs > 0 ? `${baseSlug}-${Date.now()}` : baseSlug; }, }, }), ],});Troubleshooting & Common Pitfalls
Section titled “Troubleshooting & Common Pitfalls”1. Custom Admin Controls Do Not Render (Fallback to Standard Inputs)
Section titled “1. Custom Admin Controls Do Not Render (Fallback to Standard Inputs)”If Payload Admin displays plain number or text inputs instead of the Jalali datepicker or formatted money input:
- Regenerate Payload’s Import Map by running your Payload build command:
Terminal window pnpm payload generate:importmap - Verify that React and React-DOM are version
^19.0.0to match Payload 3.
2. Money Field Validation Failure on Local API Write
Section titled “2. Money Field Validation Failure on Local API Write”If payload.create({ data: { price: 19.99 } }) fails validation:
Remember that the database field accepts only integers. Pass 1999 (in minor units) instead of 19.99.
3. Generator Endpoint Returns 401
Section titled “3. Generator Endpoint Returns 401”The generator endpoint requires an authenticated user session by default. Ensure the browser request includes credentials (credentials: "include") or pass an explicit generateSlugAccess handler in payloadFieldsPlugin.