Quickstart
Create a Ridu project with SQLite or PostgreSQL, save your first document, and read it with the generated TypeScript SDK.
This guide takes you from an empty directory to a running CMS and a typed SDK read. The Starter
template includes an authenticated users collection and a small posts collection.
You need Go 1.26 or newer, a compatible Node.js version, and one package manager:
npm, Bun, pnpm, or Yarn. Use Node.js 24 or newer for a new project. The generated admin also supports
Node.js 20.19+ on the 20.x line and 22.12+ on the 22.x line; see
Releases and compatibility. You do not need a global ridu command.
1. Choose a database and create the project
Both paths produce the same Ridu application. Choose SQLite when you want the fewest moving parts on one machine. Choose PostgreSQL when the database will be a separate service or the application may run on more than one host.
Choose SQLite in the wizard for the shortest path to a local Ridu project. It needs no database service or Docker setup. Development data lives in .ridu/development.sqlite and is created when dev starts.
SQLite is intended for a local file on one host. Before deploying, set an absolute RIDU_SQLITE_PATH and review the SQLite production guidance.
Choose PostgreSQL in the wizard for a networked database that can run independently of the application and support multiple app hosts. The generated project includes a development service on port 54329; dev starts it with Docker or OrbStack.
If you already operate PostgreSQL, set DATABASE_URL and run dev --no-docker. Production connections must use verified TLS; the PostgreSQL guide shows the complete existing-service setup.
Start the initializer with your package manager. The positional my-app names the project
directory; the wizard asks you to choose the Starter template, the database above, and optional
coding-agent guidance. The remaining commands install the workspace and start development.
npm create ridu@latest my-app
cd my-app
npm install
npm run devbun create ridu@latest my-app
cd my-app
bun install
bun run devpnpm create ridu@latest my-app
cd my-app
pnpm install
pnpm run devyarn create ridu my-app
cd my-app
yarn install
yarn run devThe initializer writes the initial migration with the generated contracts. After installing dependencies, the project is ready for its first production build.
Non-interactive scaffolding and custom package identities
Use flags for non-interactive setup or to set the Go module and npm scope. This example selects
SQLite; change --database sqlite to --database postgres for the PostgreSQL path.
npm create ridu@latest -- \
--template starter \
--database sqlite \
--module github.com/acme/content \
--scope @acme \
--no-agent \
contentbun create ridu@latest \
--template starter \
--database sqlite \
--module github.com/acme/content \
--scope @acme \
--no-agent \
contentpnpm create ridu@latest \
--template starter \
--database sqlite \
--module github.com/acme/content \
--scope @acme \
--no-agent \
contentyarn create ridu \
--template starter \
--database sqlite \
--module github.com/acme/content \
--scope @acme \
--no-agent \
contentA new named target directory must not already exist. Use . to create the project in your current
directory; Ridu warns first and stops if any project paths conflict with existing files. Replace --no-agent with
--agent codex|claude|cursor|all when automation should install agent guidance. See
Installation for every scaffold option and recovery behavior.
2. Open the admin
Keep the selected tab’s dev command running. Wait for it to print healthy API and admin URLs, then
open http://localhost:8080/admin. On an empty database Ridu shows the setup screen instead of a
login form. Create the first user with an email address and a password.
The setup operation is available only while the configured auth collection is empty. After it succeeds, the same URL shows the login screen.

3. Create your first post
Choose Posts in the sidebar, select Create new, and enter:
| Field | Value |
|---|---|
| Title | Hello from Ridu |
| Status | published |
| Author | Your new user |
Save the document. The list view should now contain Hello from Ridu.
4. Read it through the generated SDK
Open generated/ridu.generated.ts, then create scripts/read-posts.ts:
import { memoryTokenStore } from '@riducms/sdk';
import { createClient } from '../generated/ridu.generated';
const baseURL = process.env.RIDU_URL ?? 'http://localhost:8080';
const email = process.env.RIDU_EMAIL;
const password = process.env.RIDU_PASSWORD;
if (!email || !password) {
throw new Error(
'Set RIDU_EMAIL and RIDU_PASSWORD to the user created in the admin.'
);
}
// A script keeps its session token in memory and sends it on each request.
const ridu = createClient({
baseURL,
auth: { collection: 'users', token: memoryTokenStore() }
});
await ridu.auth.login({ email, password });
const page = await ridu.list('posts', {
where: { status: { equals: 'published' } },
select: { title: true, status: true },
sort: ['-createdAt']
});
console.log(page.docs);Leave the selected tab’s dev command running and execute the script in a second terminal:
RIDU_EMAIL='[email protected]' \
RIDU_PASSWORD='your-password' \
npm exec tsx -- scripts/read-posts.tsRIDU_EMAIL='[email protected]' \
RIDU_PASSWORD='your-password' \
bun scripts/read-posts.tsRIDU_EMAIL='[email protected]' \
RIDU_PASSWORD='your-password' \
pnpm exec tsx scripts/read-posts.tsRIDU_EMAIL='[email protected]' \
RIDU_PASSWORD='your-password' \
yarn tsx scripts/read-posts.tsThe output includes the post you just created. The collection slug, filter operators, selected
fields, and returned document shape are inferred from the generated contract; mistyping posts,
status, or published is a TypeScript error.
memoryTokenStore() keeps the opaque session token in memory for this process, and the SDK sends
it as Authorization: Session <token> after login. Do not log or persist it. The typed login result
is the safe session snapshot, without the token. A same-origin browser app needs no store: the SDK
uses Ridu’s HttpOnly cookie by default. A SvelteKit app on its own domain uses
@riducms/sveltekit. Long-running service clients should use an expiring API
key rather than a user’s password or session.
5. Change the model
Add a summary to content/posts.go:
var Posts = ridu.Collection{
Slug: "posts",
Access: ridu.CollectionAccess{
Create: authenticatedOnly,
Read: authenticatedOnly,
Update: authenticatedOnly,
Delete: authenticatedOnly,
},
Fields: field.Fields{
field.Text("title").Required(),
field.Textarea("summary").
MaxLength(240).
Admin(field.Admin{
Description: "A short introduction used by post cards.",
}),
field.Select("status", "draft", "published").Default("draft"),
field.Relationship("author", "users"),
richtext.Field("content"),
},
}Save the file while dev is running. Ridu regenerates the contracts, applies the additive
development change, restarts the server, and refreshes the admin. Reopen the post; the Summary
control should now be available.
Run this before committing:
ridu doctor
ridu migrate create --name add-post-summary
ridu generate --check
ridu checkReview the new migration, then commit it with generated/ and your Go config. .ridu/ remains
disposable local state. Development sync is not a deployment plan.
If something does not start
Run the doctor command from the package-manager tabs above first. If the project-local launcher is
not installed yet, repeat the matching install command from step 1 and retry. If scaffolding
stopped during Go setup, follow the exact recovery commands printed by the CLI. For an occupied
database port, either stop the conflicting local service or follow the existing-service command in
the PostgreSQL guide.
Next, learn how a Ridu project is organised, choose the right field, or read the TypeScript SDK guide. See Installation for other templates, existing services, and recovery.