Getting Started
Frontend Integration
Connect your frontend to RaisFast using the official TypeScript SDK.
The official SDK (@raisfast/sdk) is a framework-agnostic TypeScript client for the RaisFast API.
Install
pnpm add @raisfast/sdk
# or
npm install @raisfast/sdk
# or
bun add @raisfast/sdkInitialize
import { RaisFast } from "@raisfast/sdk";
const client = new RaisFast("http://localhost:9898/api/v1");The constructor accepts an optional auth store (defaults to localStorage):
import { RaisFast, LocalAuthStore } from "@raisfast/sdk";
const store = new LocalAuthStore("my_auth_key");
const client = new RaisFast("http://localhost:9898/api/v1", { authStore: store });Authentication
// Login
const result = await client.auth.login("admin@raisfast.dev", "admin123");
console.log(result.user, result.access_token);
// Register
await client.auth.register({
email: "user@example.com",
password: "strongpassword",
username: "newuser",
});
// Get current user
const me = await client.auth.getMe();
// Logout
await client.auth.logout();
// Listen to auth state changes
client.authStore.onChange((auth) => {
console.log("logged in:", !!auth?.token);
});Tokens are auto-refreshed on 401 responses — no manual refresh needed.
Query Content Types
Use client.collection() to access any content type:
// Access the "portfolios" content type
const portfolios = client.collection<Portfolio>("portfolios");
// List with pagination
const page1 = await portfolios.getList(1, 20);
console.log(page1.items); // Portfolio[]
console.log(page1.total); // total count
// List with filters, sort, and relation expansion
const result = await portfolios.getList(1, 20, {
filter: 'status = "published"',
sort: "-created_at",
expand: "category,tags",
});
// Get single item
const item = await portfolios.getOne("item_id");
// Get by filter
const item = await portfolios.getFirstListItem('slug = "my-saas"');
// Fetch all items (auto-paginates)
const all = await portfolios.getFullList();Mutate Data
// Create
const created = await portfolios.create({
title: "My SaaS App",
url: "https://mysaas.com",
tech_stack: ["Rust", "React"],
});
// Update
const updated = await portfolios.update(created.id, {
url: "https://mysaas.app",
});
// Delete
await portfolios.delete(created.id);Type Definitions
Define your types to match the content type schema:
interface Portfolio {
id: string;
title: string;
url?: string;
cover?: string;
description?: string;
tech_stack?: string[];
status: string;
created_at: string;
updated_at: string;
}
// Or generate types from CLI
// raisfast ct types portfolio -o types/portfolio.tsUse in React
import { RaisFast } from "@raisfast/sdk";
import { useEffect, useState } from "react";
const client = new RaisFast(import.meta.env.VITE_API_URL!);
function PortfolioList() {
const [items, setItems] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const portfolios = client.collection("portfolios");
portfolios
.getList(1, 20, { expand: "category,tags" })
.then((res) => setItems(res.items))
.finally(() => setLoading(false));
}, []);
if (loading) return <div>Loading...</div>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<h3>{item.title}</h3>
<p>{item.description}</p>
</li>
))}
</ul>
);
}Use in Vue
<script setup>
import { RaisFast } from "@raisfast/sdk";
import { ref, onMounted } from "vue";
const client = new RaisFast(import.meta.env.VITE_API_URL!);
const items = ref([]);
const loading = ref(true);
onMounted(async () => {
const portfolios = client.collection("portfolios");
const res = await portfolios.getList(1, 20, { expand: "category,tags" });
items.value = res.items;
loading.value = false;
});
</script>
<template>
<div v-if="loading">Loading...</div>
<ul v-else>
<li v-for="item in items" :key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</li>
</ul>
</template>Use in Vanilla JS
<script type="module">
import { RaisFast } from "@raisfast/sdk";
const client = new RaisFast("http://localhost:9898/api/v1");
const portfolios = client.collection("portfolios");
const { items } = await portfolios.getList(1, 20);
document.getElementById("list").innerHTML = items
.map((item) => `<li><h3>${item.title}</h3><p>${item.description}</p></li>`)
.join("");
</script>File Upload
const media = client.collection("portfolios");
// Upload a file
const fileInput = document.querySelector<HTMLInputElement>("#cover")!;
const file = fileInput.files![0];
await media.upload(portfolioId, file, "cover");Admin API
Admin endpoints require admin authentication:
// List all content type schemas
const schemas = await client.admin.contentTypes.list();
// List users
const users = await client.admin.users.list(1, 20);
// Manage plugins
const plugins = await client.admin.plugins.list();
await client.admin.plugins.reload("com.example.my-plugin");
// Dashboard stats
const stats = await client.admin.stats.overview();Error Handling
import { SDKError } from "@raisfast/sdk";
try {
await portfolios.getOne("invalid-id");
} catch (e) {
if (e instanceof SDKError) {
console.log(e.status); // 404
console.log(e.code); // backend error code
console.log(e.message); // "not found"
}
}Real-Time Events (SSE)
const es = client.events.subscribe();
es.addEventListener("post.created", (event) => {
console.log("New post:", JSON.parse(event.data));
});
es.addEventListener("order.paid", (event) => {
console.log("Order paid:", JSON.parse(event.data));
});
// Cleanup
es.close();Multi-Tenant
client.setTenantId("tenant-123"); // adds X-Tenant-ID header
client.setTenantId(null); // reset