For agency developers

One stack, every client.

Model each client’s content once, build their site with whatever you already use, and read it through the site’s own channel. The client edits in the Studio, and you never build another CMS admin.

your frontend

import { createBlockRegistry, createMoteurPublicClient } from '@moteurio/client';

const moteur = createMoteurPublicClient({
  baseURL: 'https://api.moteur.io',
  auth: { type: 'apiKey', apiKey: process.env.MOTEUR_KEY, projectId: 'client-site' },
});

// One block type, one component of yours.
const blocks = createBlockRegistry({
  load: type => import(`./blocks/${type}.ts`),
});

const article = await moteur.channel('public').entries.get('article', 'spring');
const body = await blocks.renderBlocks(article.data.body, 'fr');

Week one

A new client, the same week

The same steps for every project, whatever the stack.

  1. Model the content

    In the Studio or as JSON files in the project’s repository: models, blocks, shared groups of fields.

  2. Map blocks to components

    One block type, one component in your code. The client builds pages from those, and only those.

  3. Give the site a channel

    Choose the models and fields it reads, published only, and a key that can only read, from your domains.

  4. Rebuild on publish

    A signed webhook tells your host when something goes live, and previews show drafts on the real site first.

The Article model in the Studio’s Setup: seventeen fields listed with their kind, languages and whether they’re required. The Body field is open beside the list: “Blocks, a page built from blocks”, required.The Article model in the Studio’s Setup: seventeen fields listed with their kind, languages and whether they’re required. The Body field is open beside the list: “Blocks, a page built from blocks”, required.
The Article model, its Body made of blocks.

For your developers

Model it once, the way the site needs it

A model is what an entry holds. A block is what a page can be made of. You write the frontend against both, and the client’s team fills them in.

  • Forty kinds of field: text, rich text, dates, media, links to other entries, lists of blocks
  • Each field holds one value per language, or one for all
  • Models are files in the project’s Git repository: edit them in the Studio or in your editor, and roll any of them back
  • Add a field after launch and nothing breaks: existing entries simply get it, empty
  • Only builders and developers change a model, and the API holds that line, not just the Studio
How modelling works →

Beyond the API

The toolbox

Everything you’d script against a CMS, already there.

  • CLI

    A command line for everything

    Most of what the Studio does, as `moteur` commands, for scripts, CI and the evening you’d rather not click.

    • The same commands as the MCP tools
    • JSON output for your scripts

    terminal

    moteur entries list article --status in_review --json
    moteur entries update article glace --set readingTime=4
    moteur models create --file=model.json
  • Git

    Your content, in Git

    Each project is a repository of plain JSON files. Push it to your own remote, branch it, merge it.

    • A commit for every save
    • Branches through the API and CLI
  • Webhooks

    Signed webhooks

    Twenty-eight events, from a publish to a form submission, signed so your server knows it’s us.

    • Retried for two hours
    • Filtered by model, status and language

    POST to your endpoint

    {
      "event": "entry.published",
      "projectId": "client-site",
      "data": {
        "modelId": "article",
        "status": "published",
        "slug": "my-post"
      }
    }
    
    X-Moteur-Signature: sha256=…
  • Images

    Images, at the size you ask

    Every picture resized on request, in WebP or AVIF, around the focal point the client chose.

    • Cached for a year
    • Alt text in every language
  • Previews

    Drafts, on the real site

    The Studio’s preview opens your site with a short-lived token, so your site can show drafts before they go live.

    • Tokens last 30 minutes
    • Can be limited to one entry
  • Plugins

    Your own field types

    When a client needs something the 40 field types don’t cover, add a field or a block with the plugin SDK.

    • Typed, in TypeScript
    • The engine is open source

Channels

Read exactly what the site needs

A channel is what one site sees of a project: the models and fields you choose, published content only. The same read, in the stack each client’s site uses.

  • Its own OpenAPI document, to download or generate types from
  • Linked entries in the same request, up to two levels deep
  • A read-only key, limited to that channel and your domains

src/pages/index.astro

---
import { createMoteurPublicClient } from '@moteurio/client';

const moteur = createMoteurPublicClient({
  baseURL: 'https://api.moteur.io',
  auth: { type: 'apiKey', apiKey: import.meta.env.MOTEUR_KEY, projectId: 'client-site' },
});

const articles = (await moteur
  .channel('public')
  .entries.list('article', { limit: 10, sort: '-publishedAt' })) as Article[];
---

<ul>
  {articles.map(a => <li>{a.data.title.en}</li>)}
</ul>

Questions developers ask

A developer asksDo we get TypeScript types?

MoteurYes. `moteur types` writes them from the site’s channel: a type for every model, block and structure. Commit the file, and a change in the project shows up as a diff.

A developer asksWhich frameworks?

MoteurAnything that can make an HTTP request: Next.js, Astro, Nuxt, Eleventy, plain PHP. The TypeScript client helps on JavaScript sites. The REST API works everywhere.

A tech lead asksCan we version the models with our code?

MoteurModels are JSON files in the project’s Git repository. Push it to your own remote, and review a model change like any other change.

A developer asksHow do we work locally?

MoteurPoint your site at a Moteur Cloud project with its own key, or run the open-source engine on your machine.

A developer asksWhat happens when we change a model?

MoteurAdding a field is safe: existing entries get it empty. A field’s id can’t be renamed once it’s used, and every model change is a commit you can roll back.

Build your next client site on Moteur.

Start a project for free, model its content, and point your frontend at it.