A headless CMS migration fails quietly when the new system copies the old database shape instead of the real business workflow. Payload CMS gives you enough TypeScript control to avoid that mistake, but it will not do the thinking for you. Collections should describe how the company publishes, sells, reviews, and supports work, not just where old fields happened to live.
The first design question is not “what collections do we need?” It is “what decisions does the team make around this content?” A personal site needs posts, pages, media, and categories. A consulting business may need case studies, services, testimonials, lead magnets, project types, and reusable proof points. An internal product team may need approvals, ownership, release notes, and regional variants.
Model the workflow before the fields
Fields are cheap. Bad workflow is expensive. If an editor needs a draft, preview, approval, and scheduled publish step, that belongs in the model early. If a service page needs a reusable call to action and related case studies, relationships should make that easy. If authors should appear publicly without exposing user records, populate a safe author shape instead of leaking the auth collection.
Payload makes these patterns practical because the schema lives in code. You can keep collection configs close to hooks, access rules, and TypeScript types. That is a better fit for custom business sites than a CMS where every serious rule becomes a plugin negotiation. The tradeoff is discipline: because you can write code anywhere, you need to keep the model boring enough for future you to understand.
I prefer small collection boundaries with obvious ownership. A `posts` collection for articles. A `pages` collection for flexible site pages. A `services` collection only if service pages have their own lifecycle, fields, or query behavior. If services are just static landing pages, a page block may be enough. The simplest model that supports editing is usually the right one.
Access control is product behavior
Access rules are not a security afterthought. They define what the product is allowed to show. Public users can read published documents. Admin users can read drafts. Preview mode can bypass the right checks, but only in the context that proves the editor is allowed to preview. That split should be visible in the Payload config and in the frontend query helpers.
The common mistake is using `overrideAccess` too casually because it makes development easier. It also makes it easier to ship private drafts, hidden fields, or internal relationships. Use it for trusted server-side preview and migration work, then keep public queries on the same rules the site promises to users.
For client projects, this is often where trust is won. A CMS that lets marketing publish quickly is good. A CMS that lets marketing publish quickly without exposing private content, breaking previews, or asking developers for every change is better.
Relationships should reduce editing work
Relationships are useful when they remove duplicated decisions. A post can relate to categories. A case study can relate to services. A service page can pull proof points from projects. The editor should not copy the same testimonial into six pages by hand and then forget where it lives.
Do not turn every noun into a collection. A single reusable block may be enough for a callout. A global may be enough for header and footer links. A relationship is worth adding when the connected thing has its own lifecycle or is reused in enough places that duplication causes real mistakes.
This is where Payload CMS and Next.js pair well. The CMS can keep structured content clean, and the frontend can render it through a block system without hiding the data model from developers. You get editor flexibility without pretending every page is just one giant rich text blob.
Make migration prove itself
A migration from WordPress, Contentful, Sanity, or a custom admin panel should end with proof, not hope. Count documents. Check slugs. Render important pages. Verify redirects. Compare metadata. Test image variants. Confirm draft and published states. Make sure old URLs either resolve or redirect deliberately.
The migration script does not need to be beautiful. It needs to be repeatable until launch day. Keep the transforms explicit, log skipped records, and store enough source identifiers to rerun safely. A clever generic migrator is rarely needed for a one-time move. A plain script with clear checks is easier to trust.
Payload CMS is a strong choice when the site needs custom rules, real TypeScript ownership, and a CMS that can live beside the application. It works best when the model starts from the business workflow. Get that right, and the CMS stops being a content drawer and becomes part of how the company ships.