One Runtime: Sharing Code Between CMS and App in Node.js
BY LENA ORTIZ · Aug 27, 2026 · 6 MIN READ

Our old stack had two runtimes: PHP for the CMS, Node.js for the app. Two deploy pipelines, two sets of tooling, two kinds of logs — and zero code shared between them. Every CMS feature was a contract negotiation across a REST boundary.
The local API changed everything
Payload's local API runs in-process. No HTTP hop, no serialization penalty, no API versioning:
const posts = await payload.find({
collection: 'posts',
where: { 'category.slug': { equals: 'engineering' } },
})Call that from your app server, a seed script, or a migration tool — it's just a function.
Shared types, end to end
The bigger win isn't the API; it's the types. Content models defined once flow into every consumer: the admin UI, the app's server components, the validation layer, the test suite. When we add a field, the TypeScript compiler finds every place that needs to handle it.
Under WordPress, the same change meant: update the database, update the theme, update the app, and hope the REST cache doesn't serve stale shapes for a day.
What this means for migrations
When we migrate a client, the destination is never just a CMS — it's a consolidated runtime. CMS and app deploy as one unit, share one set of models, and fail in one observable place. Fewer moving parts is not just simpler; it's the whole reason the security and performance numbers in our case studies look the way they do.
Want this kind of thinking applied to your stack?
We migrate teams from WordPress, Drupal, and other legacy CMS platforms to Payload — and we publish our playbook as we go.
START A CONVERSATION