← All posts
EngineeringSep 24, 2026· 2 min read· Kanawoot K.

Why we put the CMS inside your app

A hosted headless CMS is a second service with its own deploy and database. Easy CMS is a package your app mounts instead. Here is what that changes.

Most headless CMSs are a separate service. Your site calls it over HTTPS with a token, and you keep two deployments, two databases and two sets of credentials in step. Easy CMS takes the other route: it is an npm package that runs inside your Nuxt or Next.js server.

One app, one database

The admin at /admin and the REST API at /api/cms are routes of your app. Your pages read content with the Local API, a function call in the same process, with no HTTP involved. Content lives in your database, SQLite or Postgres, in real tables and columns with an ecms_ prefix, so you can still query it with SQL.

The content model is code

Collections, fields, access rules and hooks go in easy-cms.config.ts. You review changes in pull requests, and production gets them as migrations you can read before they run.

const cms = await getEasyCMS(config)
const { docs } = await cms.find('posts', { limit: 10 })
// docs[0].title is a string, typed from the config

Typed without a build step

Because the config is TypeScript, cms.find('posts') returns typed documents straight from it. There is no schema to download and no code generation to keep up to date.

The trade-offs

  • Editors can't change the content model themselves; a developer changes the config.

  • It needs Node.js 22.12 or newer, so no edge runtimes.

  • There is no GraphQL, and the plugin ecosystem is young.

If you build with Vite, React, Vue or a static site generator, the same core runs as a standalone server with REST.

Why Easy CMS runs inside your Next.js or Nuxt app server