Thinking of leaving Contentful after the Salesforce deal? A practical guide for small teams

8 min read

Salesforce completed its purchase of Contentful on 1 September 2026. Contentful says the platform, APIs and support stay the same, and so far there's no sign of a broad price rise. Even so, if you run a few marketing sites or client sites, a renewal under a new owner is a good moment to check you're on the right tool. This guide covers how to decide, and what moving to Mojimoto actually involves.

Blocks or references?

Define the block types

In the model editor, add a field of type Blocks to your page type and describe its block types in the box. One block type per line, its fields indented beneath as name: type. Add ! to make a field required on publish, and put select options in brackets.

block types
hero: Hero
  heading: symbol!
  body: rich_text
  image: media
features: Feature list
  title: symbol!
  items: text
quote: Quote
  text: text!
  author: symbol
  tone: select(light, dark)

Block fields can be symbol, text, rich_text, number, boolean, date, select, media, location or json. Reference fields inside blocks are not supported yet - if a section needs to point at another entry, use a References field on the page for now.

Set Min and Max on the field to limit how many blocks a page can have, for example exactly one hero.

Or define them over the API

The same model as a field definition, for scripts and agents. config.blocks maps each block type to its label and fields:

add a blocks field
curl -X POST https://mojimoto.com/api/v1/your-project/manage/content-types/page/fields \
  -H "Authorization: Bearer mjmt_your_write_token" \
  -H "Content-Type: application/json" \
  -d '{
    "field": "sections",
    "definition": {
      "type": "blocks",
      "config": {
        "label": "Sections",
        "blocks": {
          "hero": {
            "label": "Hero",
            "fields": {
              "heading": { "type": "symbol", "config": { "label": "Heading", "required": true } },
              "image": { "type": "media", "config": { "label": "Image" } }
            }
          }
        }
      }
    }
  }'

Edit them

In the entry editor a Blocks field shows one card per block. Add a block from the menu of types you defined, drag cards to reorder, collapse the ones you are not working on, and remove any you no longer need. Media and rich text work inside blocks exactly as they do anywhere else.

When something is missing, publish tells you exactly where: "Sections, block 2 (Hero): Heading is required." Over the API the same error comes back keyed by position, as sections.1.data.heading.

Write them

A blocks value is an ordered list of { type, data }. Each block is delivered with an id your front end can use as a key. Blocks added in the editor keep theirs for good; when writing over the API, send your own id to keep it stable across edits.

document data
{
  "title": "Home",
  "sections": [
    { "type": "hero", "data": { "heading": "Welcome", "image": { "asset_id": 12, "fit": "cover" } } },
    { "type": "quote", "data": { "text": "It just works.", "author": "Sam" } }
  ]
}

Render them

The delivery API returns each block as { id, type, data }, with media expanded to full objects and rich text in its delivered shape. In React, SliceZone maps each block type to a component:

page.tsx
import { SliceZone, type BlockComponents } from '@mojimoto/react';

const components: BlockComponents = {
  hero: ({ slice }) => <h1>{slice.data.heading as string}</h1>,
  quote: ({ slice }) => <blockquote>{slice.data.text as string}</blockquote>,
};

export function Page({ page }) {
  return <SliceZone slices={page.data.sections} components={components} />;
}

Generated TypeScript types include a type for each block, so slice.data is fully typed once you run npx @mojimoto/cli types.

Save a template

  1. 1 Get one project's content model the way you want it. This becomes the source of the template.
  2. 2 Open your organisation settings and go to Templates.
  3. 3 Choose the project, give the template a name like "Small business site", and press Save as template.

A template holds the content model only: types, fields and their settings. Entries, media and tokens stay in the project they came from.

Next

Build it for real

Spin up a project and try this yourself - your first project is free.

© 2026 Your Ikigai Ltd · Registered in England & Wales, no. 15274889 文 · モジモト