Skip to content

Core Concepts

Before diving deeper, it helps to understand the core concepts that make up Trokky’s architecture.

Schemas define the structure of your content. Each schema represents a content type with fields that specify what data can be stored.

const postSchema = {
name: 'post', // Unique identifier
title: 'Blog Post', // Display name
fields: [
{ name: 'title', type: 'string', required: true },
{ name: 'content', type: 'richtext' },
],
};
PropertyDescription
nameUnique identifier used in API endpoints and references
titleHuman-readable name shown in Studio
fieldsArray of field definitions
singletonIf true, only one document of this type exists
previewConfiguration for document previews in Studio

Documents are instances of schemas. When you create a “Blog Post” in Studio, you’re creating a document of the post schema.

{
"_id": "abc123",
"_type": "post",
"_createdAt": "2024-01-15T10:30:00Z",
"_updatedAt": "2024-01-15T10:30:00Z",
"title": "My First Post",
"content": "Hello, world!"
}

Every document includes system fields (prefixed with _):

FieldDescription
_idUnique document identifier
_typeSchema name this document belongs to
_createdAtCreation timestamp
_updatedAtLast modification timestamp
_revRevision identifier for optimistic locking

Fields define the data structure within schemas. Trokky includes many built-in field types:

{ name: 'title', type: 'string' }
{ name: 'count', type: 'number' }
{ name: 'active', type: 'boolean' }
{ name: 'bio', type: 'text' } // Multiline string
// Date and time
{ name: 'publishedAt', type: 'datetime' }
{ name: 'birthday', type: 'date' }
// URL-friendly identifier
{ name: 'slug', type: 'slug', options: { source: 'title' } }
// Rich content
{ name: 'body', type: 'richtext' }
{ name: 'content', type: 'portabletext' }
// Media
{ name: 'image', type: 'media' }
// Reference to another document
{ name: 'author', type: 'reference', options: { to: 'author' } }
// Nested objects
{
name: 'seo',
type: 'object',
fields: [
{ name: 'title', type: 'string' },
{ name: 'description', type: 'text' },
]
}
// Arrays
{
name: 'tags',
type: 'array',
of: [{ type: 'string' }]
}

Storage adapters handle where and how content is persisted. Trokky’s adapter pattern allows you to swap storage backends without changing your application code.

Stores content as JSON files:

content/
├── post/
│ ├── abc123.json
│ └── def456.json
└── author/
└── ghi789.json

Best for: Development, Git-based workflows, simple deployments.

Stores content in AWS S3 with metadata in DynamoDB.

Best for: Scalable production deployments on AWS.

Uses Cloudflare D1 (database) and R2 (object storage).

Best for: Edge deployments on Cloudflare Workers.

Trokky’s core is framework-agnostic. Integrations adapt Trokky to specific web frameworks:

// Express
import { TrokkyExpress } from '@trokky/express';
const trokky = await TrokkyExpress.create({ ... });
trokky.mount(app);
// Next.js
import { TrokkyNextjs } from '@trokky/nextjs';
export const { GET, POST } = TrokkyNextjs.handlers({ ... });

Each integration:

  • Converts framework requests to Trokky’s internal format
  • Handles authentication middleware
  • Serves the Studio interface
  • Manages static assets

The Studio is Trokky’s admin interface - a React application for managing content.

  • Document editing: Forms generated from your schemas
  • Media library: Upload and manage images/files
  • References: Link documents together
  • Preview: See content changes in real-time
  • Multi-user: Role-based access control

Studio can be customized through configuration:

studio: {
branding: {
title: 'My CMS',
logo: '/logo.svg',
},
structure: [
{ type: 'list', schemaType: 'post', title: 'Blog Posts' },
{ type: 'list', schemaType: 'author', title: 'Authors' },
],
}

The client SDK provides a typed interface for querying content:

import { createClient } from '@trokky/client';
const client = createClient({
apiUrl: 'https://api.example.com',
});
// Typed queries
const posts = await client.documents.list('post');
const post = await client.documents.get('post', 'abc123');

Generate TypeScript types from your schemas:

Terminal window
npx trokky generate-types --output ./types/content.ts

Then use in your application:

import type { Post, Author } from './types/content';
const post: Post = await client.documents.get('post', id);

Trokky uses JWT-based authentication with role-based access control.

RolePermissions
adminFull access to all operations
editorCreate, update, delete content
writerCreate and update own content
viewerRead-only access
  1. User logs in with credentials
  2. Server validates and returns JWT token
  3. Client includes token in subsequent requests
  4. Server verifies token and checks permissions

Now that you understand the core concepts: