Skip to content
src/site/ounce.config.ts
import { defineSite } from '@ouncepage/core';
import { sections, settings } from './schema';
 
export default defineSite({
brand: 'Example CMS',
settings,
sections,
home: '/admin/pages',
plugins: [],
});

One config file, and the whole admin.

Describe your content once, in Zod schemas and field lists. Ounce gives you the admin at /admin, the routes that serve your pages, the middleware that guards them, and a typed API for reading it back.
Everything below arrives with the package. None of it is scaffolded into your repository, so none of it is yours to maintain.
An admin at /admin
Pages, settings, media, redirects, editors and revisions. Injected routes, so there is nothing in your src/pages/.
Forms from schemas
A Zod schema and a field list per content type. The forms, validation, sanitising and save path follow.
D1, R2 and Access
Content in D1, media in R2, editors authenticated by Cloudflare Access. Those three are not pluggable.
Revision history
Every save writes a revision. Restore a page or a setting to any earlier state.
Roles and editors
Three roles, checked in the middleware rather than in each screen.
Seven extension points
Field types, section types, plugins, page tabs, admin screens, analytics and assistants. Everything else is closed.