Getting started
Quickstart
From zero to a deployed schema, a published entry, and a public read — with the CLI and SDK.
This walkthrough takes you from nothing to a deployed schema, a published entry, and a public read. You need Node.js and a GitHub account.
Install and sign in
$ npm install --global @myna-sh/cli
$ myna login
# Opens app.myna.sh/device — sign in with GitHub and approve the device code.
myna login uses a browser device-authorization flow. The credential is stored in the macOS Keychain when available, otherwise in a user-only config file.
Create and link a project
$ myna organizations list
$ myna projects create --name "My site" --organization my-org
$ myna link my-site
# Writes .myna/project.json (no secrets) so later commands know the project.
Define a schema
myna init scaffolds a myna/ directory with an example collection:
import { collection, field } from "@myna-sh/sdk/schema";
export const posts = collection({
name: "posts",
label: "Blog posts",
visibility: "public",
titleField: "title",
path: "/blog/{slug}",
fields: {
title: field.text({ required: true, maxLength: 120 }),
slug: field.slug({ from: "title", required: true }),
description: field.text({ multiline: true }),
body: field.markdown({ required: true }),
cover: field.asset({ allowed: ["image/*"] }),
publishedAt: field.datetime(),
},
});
Schemas are code-owned: the dashboard displays them but the source of truth is this file. Deploy it:
$ myna schema diff
$ myna schema push
diff shows a stable plan and classifies each operation; destructive changes require --allow-destructive. Every push creates an immutable schema version.
Create and publish an entry
$ myna entries create posts --set title="Hello world" --set body="First post."
# Creates a draft revision on an implicit change set. Nothing is public yet.
$ myna changes list
$ myna changes publish <chs_id> --confirm-publish
Writes are drafts until a change set is published. Publishing validates every item and updates all published pointers in one transaction.
Read published content
import { createMyna } from "@myna-sh/sdk";
const myna = createMyna({ project: "my-site" });
const { data } = await myna.entries.list("posts", {
order: "-publishedAt",
limit: 10,
});
const post = await myna.entries.get("posts", "hello-world");
In a React app, @myna-sh/react wraps the same client with hooks that share requests, carry loading and error state, and pass a preview token through the tree:
const { data, error, isLoading } = useMynaEntries("posts", { order: "-publishedAt" });
Public collections need no credentials. Or use plain HTTP:
$ curl https://api.myna.sh/v1/projects/my-site/collections/posts/entries
Generate types
$ myna types generate --out src/myna.generated.ts
Emits deterministic TypeScript interfaces for your collections — same input, byte-identical output, safe to commit.
Pass the generated registry to createMyna and reads are typed end to end:
import { createMyna } from "@myna-sh/sdk";
import type { MynaCollections } from "./myna.generated";
const myna = createMyna<MynaCollections>({ project: "my-site" });
const { data } = await myna.entries.list("posts", { order: "-publishedAt" });
data[0].fields.title; // string
Collection keys, field names, and sortable fields are all checked — see generated types.
Next
- Change sets and publishing — the core workflow in depth.
- Using Myna with agents — scoped keys, MCP setup, and the review loop.
