What is NotCMS?

NotCMS is a headless CMS that uses Notion as your content backend, providing the best of both worlds: Notion’s intuitive editor for content creators and a type-safe API for developers.

Type Safety

End-to-end type safety from schema to queries with excellent developer experience. Full TypeScript support ensures no runtime type errors.

Familiar Editor

Use Notion’s editor your team already knows. No need to learn a new CMS interface - content creators stay productive from day one.

Simple Setup

Get started in minutes with our CLI tool. No complex configuration or infrastructure setup required.

Real-time Updates

Content changes in Notion are immediately available through the API. No build step or manual sync needed.

Core Concepts

Type-Safe Queries

Query your content with full TypeScript support:
import { Client } from "notcms";
import { schema } from "./schema";

const nc = new Client({ schema });

// Fully typed response
const [posts, error] = await nc.query.blog.list();
// posts: Array<{
//   title: string,
//   content: string,
//   properties: {
//     published: boolean,
//     author: string
//   }
// }>

Schema-First Approach

NotCMS generates TypeScript schemas from your Notion databases, ensuring type safety throughout your application:
// Auto-generated schema
export const schema = {
  blog: {
    id: "your_database_id",
    properties: {
      title: "title",
      published: "checkbox",
      author: "rich_text",
    },
  },
} satisfies Schema;

Error Handling

NotCMS uses a tuple-based error handling pattern for predictable error management:
const [data, error, response] = await nc.query.blog.get(pageId);

if (error) {
  console.error("Failed to fetch:", error.message);
  return;
}

// Use data safely
console.log(data.title);

Why NotCMS, instead of raw Notion API?

While Notion’s API is powerful, using it directly for content management comes with significant challenges:

Challenges with raw Notion API

  • Complex API queries: You need to learn Notion’s intricate query syntax and property structures
  • No TypeScript support: Query results lack type definitions, leading to runtime errors and poor IDE support
  • Maintenance nightmare: When you update Notion properties, you must manually update code across your entire application
  • Content transformation: You need to write custom code to convert Notion blocks to Markdown or HTML
  • Image hosting issues: Notion image URLs expire, requiring you to implement your own image re-hosting solution

How NotCMS solves these problems

NotCMS handles all these complexities for you:
// ❌ Raw Notion API - Complex and error-prone
const response = await notion.databases.query({
  database_id: "abc123",
  filter: {
    property: "Published",
    checkbox: { equals: true },
  },
});
// No TypeScript support, manual type assertions needed
const title = (response.results[0].properties.Title as any).title[0].plain_text;

// ✅ NotCMS - Simple and type-safe
const [posts, error] = await nc.query.blog.list();
// Full TypeScript support, IDE autocomplete works
posts.forEach((post) => console.log(post.title));
With NotCMS, you get:
  • Auto-generated TypeScript types from your Notion databases
  • Simple, intuitive API that feels natural to JavaScript developers
  • Automatic content transformation to Markdown
  • Persistent image hosting that comes out of the box
  • Instantly pull updates with CLI when your Notion schema changes

Next Steps