SDKs & Client Libraries

Type-safe libraries and clients to deliver SCHMA content into your web applications, mobile apps, and edge functions.

Overview

The official @schmadev/client package provides an idiomatic, lightweight TypeScript client for querying published content from SCHMA. It handles authentication, URL synthesis, query string serialization, environment routing, and JSON response normalization out of the box.

Zero dependenciesFull TypeScript genericsEdge & Node.js runtime compatible

Installation

Install the client package into your project using your preferred package manager:

Terminal
# npm
npm install @schmadev/client

# pnpm
pnpm add @schmadev/client

# bun
bun add @schmadev/client

Initialize the client

Initialize the client with your Delivery API key and workspace tenant slug. We recommend creating a dedicated client file (e.g. src/lib/schma.ts) to reuse across your application.

src/lib/schma.ts
import { createClient } from "@schmadev/client";

export const schma = createClient({
  apiKey: process.env.SCHMA_DELIVERY_API_KEY!,
  tenantSlug: process.env.SCHMA_TENANT_SLUG!,
  baseUrl: process.env.SCHMA_API_URL || "https://api.schma.dev",
  environment: "production", // optional, defaults to "production"
});
SchmaClient configuration options
OptionTypeDescription
apiKeystring | () => Promise<string>Delivery API key with read permissions.
tenantSlugstringWorkspace slug (e.g. acme-corp).
baseUrlstringAPI server URL (defaults to https://api.schma.dev).
environmentstringPostgreSQL environment schema (defaults to production).

Querying content: Delivery methods

The schma.delivery namespace provides methods for querying published entries:

List published entries

Filter, sort, and paginate through entries of a given content model:

List entries
// Fetch published blog posts
const { entries, meta } = await schma.delivery.listEntries({
  type: "post",
  limit: 10,
  offset: 0,
  sortBy: "createdAt",
  order: "desc",
});

console.log(`Fetched ${entries.length} of ${meta.total ?? meta.count} entries`);

Get entry by ID

Retrieve a specific published entry by UUID:

Get single entry
// Fetch a single entry by UUID
const post = await schma.delivery.getEntry({
  id: "e4b27c62-1a3f-4e89-b765-92c10df48e01",
  locale: "en-US", // optional locale
});

console.log(post.title, post.data.content);

Semantic similarity search

Perform natural-language vector similarity queries against your published content (available on Pro and Max tiers):

Vector search
// Semantic vector similarity search (Pro & Max)
const results = await schma.delivery.searchSimilar({
  text: "PostgreSQL database configuration and migrations",
  limit: 5,
});

for (const entry of results.entries) {
  console.log(entry.id, entry.data.title);
}

TypeScript end-to-end typing

All delivery methods accept a generic type parameter <T> that flows directly into entry.data:

Type safety example
interface BlogPost {
  title: string;
  slug: string;
  content: string;
  publishedDate: string;
  author: {
    name: string;
    avatarUrl?: string;
  };
}

// Pass your type to listEntries for end-to-end type safety
const { entries } = await schma.delivery.listEntries<BlogPost>({
  type: "post",
  limit: 5,
});

entries.forEach((post) => {
  // post.data is fully typed as BlogPost
  console.log(post.data.title.toUpperCase());
});

To generate TypeScript interfaces automatically from your live PostgreSQL schema, use the SCHMA CLI code generator (schma generate).

Framework integration: Next.js App Router

Because @schmadev/client uses standard fetch under the hood, it seamlessly integrates with React Server Components and Next.js caching:

Next.js Server Component
// app/blog/page.tsx (Next.js 15 Server Component)
import { schma } from "@/lib/schma";

interface Article {
  title: string;
  summary: string;
}

export default async function BlogPage() {
  const { entries: articles } = await schma.delivery.listEntries<Article>({
    type: "article",
    limit: 20,
  });

  return (
    <main className="max-w-4xl mx-auto py-12 px-6">
      <h1 className="text-3xl font-bold mb-8">Latest Articles</h1>
      <div className="grid gap-6">
        {articles.map((item) => (
          <article key={item.id} className="p-6 border rounded-lg">
            <h2 className="text-xl font-semibold">{item.data.title}</h2>
            <p className="text-zinc-400 mt-2">{item.data.summary}</p>
          </article>
        ))}
      </div>
    </main>
  );
}

To trigger on-demand cache revalidation when editors publish new content in Studio, set up an ISR webhook handler:

Read the Webhook Revalidation guide →

Next steps & related resources