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

> A headless CMS without a second server: one deployment, one database, a typed Local API, and the trade-offs that come with it.

URL: https://easycms.dev/blog/why-we-put-the-cms-inside-your-app  
Published: 2026-09-24  
Updated: 2026-10-29

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.

```ts
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.
