RaisFastRaisFast
Full-Stack Development

Data & CRUD

Define custom data models in TOML, get auto-generated REST APIs, and build the frontend data layer.

The Flow

TOML Definition → Auto DB Table → Auto CRUD API → Frontend Data Layer

You define the schema once. RaisFast handles the rest.

Step 1 — Define a Content Type

Create a TOML file in your project:

name = "Article"
table = "articles"
plural = "articles"

[fields.title]
type = "text"
required = true
index = true

[fields.slug]
type = "text"
required = true
unique = true

[fields.body]
type = "rich_text"

[fields.excerpt]
type = "text"
max_length = 500

[fields.cover_image]
type = "media"
accept = "image/*"

[fields.category]
type = "relation"
related_type = "categories"
relation = "many_to_one"

[fields.tags]
type = "relation"
related_type = "tags"
relation = "many_to_many"

[fields.status]
type = "enum"
options = ["draft", "published", "archived"]
default = "draft"

[fields.published_at]
type = "timestamp"

Restart the server. The table and API are created automatically.

Step 2 — Use the Auto-Generated API

MethodEndpointDescription
GET/api/v1/admin/cms/articlesList (with pagination, filters, search)
POST/api/v1/admin/cms/articlesCreate
GET/api/v1/admin/cms/articles/:idGet by ID
PUT/api/v1/admin/cms/articles/:idUpdate
DELETE/api/v1/admin/cms/articles/:idDelete

Query Examples

# List with pagination
GET /api/v1/admin/cms/articles?page=1&limit=10

# Filter by status
GET /api/v1/admin/cms/articles?status=published

# Search
GET /api/v1/admin/cms/articles?search=introduction

# Sort by date descending
GET /api/v1/admin/cms/articles?sort=created_at&order=desc

Step 3 — Frontend Data Layer

import { client } from "@/lib/client";

// List articles
const { data } = await client.contentTypes.list("articles", {
  page: 1,
  limit: 10,
  status: "published",
  sort: "created_at",
  order: "desc",
});

// Create article
const article = await client.contentTypes.create("articles", {
  title: "My Article",
  slug: "my-article",
  body: "<p>Content here</p>",
  status: "draft",
});

// Update article
await client.contentTypes.update("articles", article.id, {
  status: "published",
});

// Delete article
await client.contentTypes.delete("articles", article.id);
import { client } from "@/lib/client";

// List articles
const { data } = await client.contentTypes.list("articles", {
  page: 1,
  limit: 10,
  status: "published",
  sort: "created_at",
  order: "desc",
});

// Create article
const article = await client.contentTypes.create("articles", {
  title: "My Article",
  slug: "my-article",
  body: "<p>Content here</p>",
  status: "draft",
});

// Update article
await client.contentTypes.update("articles", article.id, {
  status: "published",
});

// Delete article
await client.contentTypes.delete("articles", article.id);

Available Field Types

TypeDescriptionExample Use
textShort text (up to 255 chars)Title, name
rich_textLong HTML contentBody, description
numberInteger or floatPrice, quantity
booleanTrue/falsePublished, active
enumPredefined optionsStatus, role
timestampDate/timeCreated at, scheduled
mediaFile uploadCover image, attachment
relationLink to another typeAuthor, category
jsonArbitrary JSON dataMetadata, settings

Relations

# Many-to-one: each article belongs to one category
[fields.category]
type = "relation"
related_type = "categories"
relation = "many_to_one"

# Many-to-many: articles can have multiple tags
[fields.tags]
type = "relation"
related_type = "tags"
relation = "many_to_many"

# One-to-one: a user has one profile
[fields.profile]
type = "relation"
related_type = "profiles"
relation = "one_to_one"

Next Step

Ready to build a real project? Follow the Blog Tutorial.

On this page