Everything is a Node
One recursive JSON structure for everything. Pages, tables, content, and files.
The Coreless Protocol
A strict, human-readable JSON schema. Every object follows the same Node interface.
Recursive Structure
Folders contain children. Children can be folders. Infinite nesting.
Strict Typing
Every node has a defined type and predictable data schema.
interface Node {
type: "folder" | "text" | "image" | "table";
name: string;
slug: string; // kebab-case
data: Record<string, any>;
children?: Node[];
}
Native Node Types
Built-in primitives to construct any content model without complex migrations.
{ children: [...] }
{ data: { content: "..." } }
{ data: { url: "...", size: 1024 } }
{ data: { fields: [...] }, children: [row] }
{ data: { [slug]: value } }
{ data: { content: "# Markdown..." } }
Universal Architecture
Whether it's a Landing Page (folders & blocks) or a Knowledge Base (tables & rows), it's all just a tree of nodes.
Landing Page Structure
├─ folder (hero)
│ ├─ text (title)
│ └─ image (cover)
└─ folder (about)
Knowledge Base Structure
├─ table (categories)
└─ table (articles)
└─ row (article_1)
JSON Import / Export
Since the entire structure is just a JSON tree, you can export your entire project state to a file, commit it to Git, or import it into a new environment instantly.
coreless-lib — official client
TypeScript / JavaScript library on npm. Wraps the same HTTP API; use it anywhere from static HTML to Next.js App Router. React is optional.
- ✓Framework-agnostic core — import from coreless-lib or coreless-lib/core
- ✓ContentClient: .text(), .image(), .video(), .file(), .list(), .table(), .field(), .node() by slash path
- ✓Tables: offset/limit, exclude_fields, search, filter — passed as query params on fetch
- ✓Coreless extras: getNode(path), getRow(page, table, row), getTable(page, table, params)
- ✓useContent(slug) for CSR; for RSC use await new Coreless(...).getPage(slug) in a Server Component
- ✓Peer dependency: react — optional; install only if you use CorelessProvider / useContent
Install
Coreless class
HttpContentFetcher calls GET /content/{projectSlug}/{path}. Coreless.getPage() returns a ContentClient with path-based helpers.
React
CorelessProvider + HttpContentFetcher at the app root; useContent(pageSlug) exposes the same methods plus loading, error, and refresh().
How your app reads content
Same idea as Project → API docs: one JSON tree per page, then typed helpers for each field path.
Example only: project slug acme-studio, page home — paths match folder/block slugs in the tree.
REST
Public content endpoint returns the full page tree. Matches GET used by the dashboard (see api.nodes.getContent).
Typed helpers
After cms.getPage(pageSlug), use .text(), .image(), .table()… with paths like hero/title — the same shape auto-generated in project API docs.
Fetch from your frontend
Direct fetch with the same URL and auth headers as in lib/api.ts.