Skip to content
Esc
navigateopen⌘Jpreview
On this page

Quickstart

Install the Vite plugin, point it at your organization, and go from an empty project to a typed content client in four steps.

Getting from an empty project to typed content is four steps. Everything after that happens on its own: the client regenerates whenever the model changes.

Create an API key

API keys are scoped to an organization. In the Stet app, open Developers → API keys and create one. You need to be an owner or admin of the organization. Copy the key while it is on screen: only its hash is stored, so it is shown once. The authentication reference has the detail.

Export it, along with the origin if you self-host:

export STET_API_KEY="..."

# Only if you self-host. The default is the hosted cloud.
export STET_ORIGIN="https://stet.example.com"

Install the packages

npm install @stetcms/vite @stetcms/client
pnpm add @stetcms/vite @stetcms/client
yarn add @stetcms/vite @stetcms/client
bun add @stetcms/vite @stetcms/client

The plugin generates the client; @stetcms/client is what the generated file imports at runtime, so both belong in your dependencies.

Add the plugin

import { stet } from '@stetcms/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [stet()],
});

That is the whole setup. The plugin writes src/stet.gen.ts before every build and dev-server start, and keeps watching while the dev server runs, so a field your content team adds in the UI reaches your types a few seconds later.

Read your content

import { stet } from './stet.gen';

const posts = await stet.posts.list();
const post = await stet.posts.get('hello-world');

post.title;
post.fields.body; // markdown
post.fields.cover?.url; // a whole, public URL

The keys on stet are your organization’s collections and maps, and the fields on an entry are the ones your content team defined. Both autocomplete.

Add a config file

The plugin runs with no configuration. Add stet.config.ts at your project root when you want to move the generated file, pin an origin, or declare an analytics tracking plan:

import { defineStet } from '@stetcms/config';

export default defineStet({
  output: 'src/lib/stet.gen.ts',
});

The CLI reads the same file, so stet generate in CI writes exactly where your dev server does. See the configuration reference for every option and how they resolve.

Generate without a dev server

CI and one-off scripts do not run Vite. The CLI does the same codegen:

npx stet generate

Where content is read from

The generated client talks to the Stet API from your server, never from a browser. In a framework with server-side data loading, that means a loader, a server function, or a route handler:

import { createServerFn } from '@tanstack/react-start';
import { stet } from './stet.gen';

export const getPosts = createServerFn().handler(() => stet.posts.list());
import { stet } from './stet.gen';

export default async function Page() {
  const posts = await stet.posts.list();
  return <PostList posts={posts} />;
}
---
import { stet } from '../stet.gen';

const posts = await stet.posts.list();
---

Next

Was this page helpful?