Skip to main content

How Contember works

Contember Engine lets you define your own data model with TypeScript and instantly turns it into a GraphQL API. It is a standalone server, which provides an extensive GraphQL API for your data - we call it the Content API. Contember API also provides, what we call a Tenant API which handles authentication and authorization, so you can control who and how can access your data.

Contember Interface is an SDK for building custom management interfaces. It lets you define your own management UI with high-level React components and automatically connects to GraphQL provided by Contember Engine.

We believe the code is the best way to express your needs. You can also easily version your project with Git, collaborate with team members and share or reuse.

contember diagram

How the project looks like

First you have to tell Contember Engine, how your data model looks like. So you start defining your project schema. For the most simple blog, it could look something like this:

// Post.ts

import { SchemaDefinition as def } from '@contember/schema-definition'

export class Post {
title = def.stringColumn().notNull()
publishedAt = def.dateTimeColumn()
content = def.stringColumn().notNull()

We use TypeScript for schema definition.

Contember Engine then creates a table in a PostgreSQL database, where it stores your data and instantly provides you with GraphQL API.

To save a post using GraphQL API, just fire this mutation:

mutation {
data: {
title: "Hello world",
content: "first article stored in Contember!",
publishedAt: "2019-12-11T16:35:06"
) {
node {

To list all published posts, you can use this query:

query {
listPost(filter: {publishedAt: {isNull: false}}) {

Of course, Contember Engine also works with complex structures, and you can define any kind of relationships between entities. Find out more in a chapter defining schema.

With Contember Interface you can create any management interface you want. For example the post edit page will be as simple as this:

export const postEdit = (
<EditPage entity="Post(id = $id)">
<TextField field="title" label="Title" />
<TextAreaField field="content" label="Content" />
<DateTimeField field="publishedAt" label="Published at" />

Check the quickstart and try it by yourself in a few minutes.