Developer experience

Keep your content model close to your code.

Collections, globals, and loaders live in the repo. Types come from the schema — not a dashboard export you have to regenerate.

  • TypeScript-first

    defineCollection and defineGlobal are typed APIs. Field types, access, and relations are checked when you compile the app — before anyone opens the CMS.

  • Schema in code

    The content model is a file in git. Review it in a pull request. Branch it. There is no hidden dashboard state that drifts from production.

  • Fully typed queries

    stackpress.find and getGlobal infer the document from the collection slug and the populate list. Loaders return real types, not unknown.

  • Relations & media

    Uploads and relations are fields, not plugins. Populate them in the same query you already write. The inferred type expands with them.

  • Server-side loaders

    Call Stackpress from TanStack Start loaders, server functions, or any server module. The CMS is the editor; your framework is still the app.

  • No duplicated models

    You do not maintain a Zod schema, a CMS config, and a TypeScript interface for the same post. One definition feeds the admin and the client.

1import { defineCollection } from 'stackpress/config'
2 
3export const posts = defineCollection('posts', {)
4 fields: {
5 title: { type: 'text', required: true },
6 author: { type: 'relation', to: 'authors' },
7 cover: { type: 'upload' },
8 },
9 access: { read: () => true },
10})

Content infrastructure, without the abstraction tax.

Define your model in TypeScript. Give your team a powerful editing experience. Ship typed content wherever you need it.

Open the CMS