### Full UI Configuration Example Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md A complete example demonstrating branding and grouped navigation within the main config. ```typescript export default config({ storage: { kind: 'local' }, ui: { brand: { name: 'Acme CMS', mark: ({ colorScheme }) => ( A ), }, navigation: { 'Blog': ['posts', 'categories', 'authors'], 'Pages': ['pages'], '---': [], 'Settings': ['navigation', 'siteConfig'], }, }, collections: { /* ... */ }, }); ``` -------------------------------- ### Format Configuration Examples Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Examples showing simple format strings and object configurations for content fields. ```typescript // Simple format format: 'json' // Separate content field format: { data: 'yaml', contentField: 'content' } // Multiple content fields format: { data: 'yaml', contentField: ['content', 'excerpt'] } ``` -------------------------------- ### Example Collection Configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Demonstrates how to instantiate a collection with various fields and settings. ```typescript const blogPosts = collection({ label: 'Blog Posts', path: 'blog/posts/**', format: { data: 'yaml', contentField: 'content' }, entryLayout: 'content', previewUrl: '/blog/{slug}', columns: ['title', 'date', 'status'], slugField: 'slug', schema: { title: fields.text({ label: 'Title' }), slug: fields.slug({ label: 'Slug' }), date: fields.date({ label: 'Date' }), status: fields.select({ label: 'Status', options: [ { label: 'Draft', value: 'draft' }, { label: 'Published', value: 'published' }, ], defaultValue: 'draft', }), content: fields.document({ label: 'Content' }), }, }); ``` -------------------------------- ### Example Singleton Configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Demonstrates how to instantiate a singleton entry. ```typescript const homepage = singleton({ label: 'Homepage', path: 'pages/home', format: 'json', schema: { title: fields.text({ label: 'Hero Title' }), description: fields.text({ label: 'Description', multiline: true }), featuredImage: fields.image({ label: 'Featured Image' }), }, }); ``` -------------------------------- ### Configure for Local Development Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/api-handler.md Example configuration and API route handler setup for local storage mode. ```typescript // keystatic.config.ts import { config } from '@keystatic/core'; export default config({ storage: { kind: 'local' }, collections: { /* ... */ }, }); // api/keystatic/[...params].ts import { makeGenericAPIRouteHandler } from '@keystatic/core/api/generic'; import config from '@/keystatic.config'; export default makeGenericAPIRouteHandler({ config, // No clientId/clientSecret needed for local mode localBaseDirectory: process.cwd(), }); ``` -------------------------------- ### Install Keystatic Dependencies Source: https://github.com/thinkmill/keystatic/blob/main/templates/nextjs/README.md Run this command in your terminal to install the necessary project dependencies. ```bash npm install ``` -------------------------------- ### Build and Start Remix for Production Source: https://github.com/thinkmill/keystatic/blob/main/templates/remix/README.md Commands to compile the application for production and launch the server. ```sh npm run build ``` ```sh npm start ``` -------------------------------- ### Install Keystatic with pnpm Source: https://github.com/thinkmill/keystatic/blob/main/README.md Install Keystatic dependencies using pnpm. Ensure you have Node.js v18 and pnpm installed. ```sh pnpm install ``` -------------------------------- ### Run Development Server Source: https://github.com/thinkmill/keystatic/blob/main/dev-projects/next-blocks-builder/README.md Use these commands to start the local development server for your Next.js project. Open http://localhost:3000 in your browser to view the application. ```bash npm run dev ``` ```bash yarn dev ``` ```bash pnpm dev ``` ```bash bun dev ``` -------------------------------- ### Run Keystatic Development Server Source: https://github.com/thinkmill/keystatic/blob/main/templates/nextjs/README.md Execute this command to start the development server for your Next.js application with Keystatic. ```bash npm run dev ``` -------------------------------- ### Run Keystatic Development Project Source: https://github.com/thinkmill/keystatic/blob/main/README.md Navigate to a development project and start the development server using pnpm. This is for local development and testing of Keystatic features. ```sh cd dev-projects/{example} pnpm run dev ``` -------------------------------- ### Configure Collection Paths Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Examples of using glob patterns to define flat or nested directory structures for content. ```typescript // Flat structure: content/posts/{slug} path: 'content/posts/*' // Nested structure: content/blog/2024/06/{slug} path: 'content/blog/**' ``` -------------------------------- ### Mount Admin Component with Custom Path Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Example of mounting the Admin interface at a custom URL path using the basePath prop. ```typescript // Admin UI at /cms instead of /keystatic export default function AdminPage() { return ; } ``` -------------------------------- ### Define Entry Schema and Result Type Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/types.md Example of a collection schema definition and the resulting TypeScript interface for the entry reader. ```typescript { title: fields.text({ label: 'Title' }), slug: fields.slug({ label: 'Slug' }), date: fields.date({ label: 'Date' }), author: fields.relationship({ label: 'Author', collection: 'authors' }), tags: fields.multiselect({ label: 'Tags', options: [...] }), } ``` ```typescript { title: string; slug: string; date: string; // ISO format author: string; // slug of author tags: string[]; // selected tag values } ``` -------------------------------- ### Create Keystatic Project Source: https://github.com/thinkmill/keystatic/blob/main/packages/create/README.md Use this command to initiate the creation of a new Keystatic project from your CLI. ```bash npx create @keystatic ``` -------------------------------- ### Run Keystatic Create Locally Source: https://github.com/thinkmill/keystatic/blob/main/packages/create/README.md To test local changes to the create package, run this command. You can specify absolute paths for project creation. ```bash pnpm dev:create ``` -------------------------------- ### Initialize a local file system reader Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Creates a reader instance for a local repository. Requires an absolute path and the Keystatic configuration object. ```typescript import { createReader } from '@keystatic/core/reader'; import config from '@/keystatic.config'; import path from 'path'; const reader = createReader( path.join(process.cwd()), config ); // Read a single entry const post = await reader.collections.posts.read('my-post-slug'); // Read all entries const allPosts = await reader.collections.posts.all(); // Read a singleton const settings = await reader.singletons.settings.read(); ``` -------------------------------- ### Project Directory Structure Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Overview of the Keystatic package source directory layout. ```text /packages/keystatic/src/ ├── index.ts # Main exports: config, collection, singleton, fields ├── config.tsx # Config types and functions ├── reader/ # Build-time readers │ ├── index.ts # Local reader (createReader) │ └── github.ts # GitHub reader (createGitHubReader) ├── form/ # Form field definitions │ ├── api.tsx # Field type definitions │ └── fields/ # Individual field implementations ├── api/ # API route handler │ └── generic.ts # makeGenericAPIRouteHandler ├── renderer.tsx # Document rendering (defaultRenderers) ├── content-components.ts # Content component definitions └── ui.tsx # Admin component (Admin) ``` -------------------------------- ### Semantic Text Variant Definition Source: https://github.com/thinkmill/keystatic/blob/main/design-system/primitives/README.md Shows an example of defining text variants using semantic names like 'caption' instead of t-shirt sizes. This approach consolidates font properties such as color, family, size, weight, line height, and text transform under a single semantic token. ```json { "color": "{some.value}", "fontFamily": "{some.value}", "fontSize": "{some.value}", "fontWeight": "{some.value}", "lineHeight": "{some.value}", "textTransform": "{some.value}" } ``` -------------------------------- ### Define project configuration with config Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Initializes the Keystatic project configuration, including storage, collections, and singletons. ```typescript import { config, collection, singleton, fields } from '@keystatic/core'; export default config({ storage: { kind: 'github', repo: 'your-org/your-repo', }, collections: { posts: collection({ label: 'Blog Posts', slugField: 'slug', schema: { title: fields.text({ label: 'Title' }), slug: fields.slug({ label: 'Slug' }), content: fields.document({ label: 'Content' }), }, }), }, singletons: { settings: singleton({ label: 'Site Settings', schema: { siteName: fields.text({ label: 'Site Name' }), }, }), }, }); ``` -------------------------------- ### Initialize a GitHub repository reader Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Creates a reader instance for a GitHub repository. Authentication via a personal access token is recommended for private repositories and to avoid rate limits. ```typescript import { createGitHubReader } from '@keystatic/core/reader/github'; import config from '@/keystatic.config'; const reader = createGitHubReader(config, { repo: 'acme/website', ref: 'main', token: process.env.GITHUB_TOKEN, }); // Read from a specific branch const reader = createGitHubReader(config, { repo: 'acme/website', ref: 'develop', }); // Read with path prefix const reader = createGitHubReader(config, { repo: 'acme/website', pathPrefix: 'content', ref: 'main', }); ``` -------------------------------- ### Set Up Environment Variables for Keystatic Dev App Source: https://github.com/thinkmill/keystatic/blob/main/dev-projects/next-app/README.md These environment variables are required to run the Keystatic development application. Ensure they are set in a `.env` file. ```bash KEYSTATIC_SECRET=... KEYSTATIC_GITHUB_CLIENT_ID=... KEYSTATIC_GITHUB_CLIENT_SECRET=... ``` -------------------------------- ### Configure reader environment variables Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Optional environment variable for build-time access to private repositories. ```bash # GitHub token (optional, for private repos) GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` -------------------------------- ### config() Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Validates and returns the Keystatic configuration object. ```APIDOC ## config() ### Description Validates and returns the configuration for a Keystatic project. ``` -------------------------------- ### Configure GitHub Storage Environment Variables Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Required environment variables for GitHub-backed storage. Ensure these are set in your deployment environment. ```bash KEYSTATIC_GITHUB_CLIENT_ID=your_client_id KEYSTATIC_GITHUB_CLIENT_SECRET=your_client_secret KEYSTATIC_SECRET=any_random_string ``` -------------------------------- ### Configure UI Environment Variables Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Set these environment variables to customize the API path, enable debug logging, or point to a custom cloud endpoint. ```bash # Set custom API base path (default: /api/keystatic) KEYSTATIC_API_PATH=/custom/api/path # Enable debug logging KEYSTATIC_DEBUG=true # Custom cloud endpoint KEYSTATIC_CLOUD_API=https://custom.cloud.keystatic.com ``` -------------------------------- ### Configure Keystatic Collections and Singletons Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Defines the CMS structure including storage, collections, singletons, and UI branding. Requires importing core functions from @keystatic/core. ```typescript import { config, collection, singleton, fields } from '@keystatic/core'; export default config({ storage: { kind: 'github', repo: { owner: 'acme', name: 'website' }, }, collections: { posts: collection({ label: 'Blog Posts', slugField: 'slug', schema: { title: fields.text({ label: 'Title' }), slug: fields.slug({ label: 'URL Slug' }), date: fields.date({ label: 'Date', defaultValue: { kind: 'today' } }), author: fields.relationship({ label: 'Author', collection: 'authors' }), content: fields.document({ label: 'Content', formatting: { inlineMarks: ['bold', 'italic', 'code'], headingLevels: [1, 2, 3], }, images: true, tables: true, }), }, }), }, singletons: { settings: singleton({ label: 'Site Settings', schema: { siteName: fields.text({ label: 'Site Name' }), tagline: fields.text({ label: 'Tagline' }), }, }), }, ui: { brand: { name: 'Acme CMS' }, navigation: ['posts', 'settings'], }, }); ``` -------------------------------- ### Import Keystatic Admin Component Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Import the main admin interface component from the Keystatic UI entry point. ```typescript import { Admin } from '@keystatic/core/ui'; ``` -------------------------------- ### Static Generation from GitHub Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Initializes a GitHub-based reader to fetch content directly from a remote repository. ```typescript // scripts/build-site.ts import { createGitHubReader } from '@keystatic/core/reader/github'; import config from '@/keystatic.config'; const reader = createGitHubReader(config, { repo: 'acme/website', ref: 'main', token: process.env.GITHUB_TOKEN, }); async function generateSitemap() { const posts = await reader.collections.posts.all(); const urls = posts.map(({ slug }) => `https://acme.com/blog/${slug}`); // Generate sitemap.xml } generateSitemap(); ``` -------------------------------- ### Configure local file system storage Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Configuration schema for local development and testing environments. ```typescript type LocalConfig = { storage: { kind: 'local' }; collections?: Collections; singletons?: Singletons; locale?: Locale; ui?: UserInterface; } ``` ```typescript import { config } from '@keystatic/core'; export default config({ storage: { kind: 'local' }, collections: { posts: collection({ /* ... */ }), }, }); ``` -------------------------------- ### Configure singleton file path Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Specifies the file system path for singleton data, supporting custom extensions and directory nesting. ```typescript path?: string ``` ```typescript // Default: config/{singleton}.yaml path: 'config/settings' // Custom extension: config/settings.json path: 'config/settings.json' // Nested: data/site/config path: 'data/site/config' ``` -------------------------------- ### Exported members from @keystatic/core/reader/github Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/STRUCTURE.md GitHub-specific reader initialization. ```typescript createGitHubReader ``` -------------------------------- ### Configure API handler environment variables Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Required environment variables for GitHub storage integration. ```bash # GitHub OAuth app credentials KEYSTATIC_GITHUB_CLIENT_ID=your_client_id KEYSTATIC_GITHUB_CLIENT_SECRET=your_client_secret # Session encryption key (any random string) KEYSTATIC_SECRET=super_secret_random_string ``` -------------------------------- ### Configure Preview URL Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Sets the template URL for previewing content with support for placeholders. ```typescript previewUrl?: string ``` ```typescript collection({ label: 'Blog Posts', previewUrl: '/blog/{slug}', // or with environment previewUrl: process.env.NEXT_PUBLIC_SITE_URL + '/blog/{slug}', // ... }) ``` -------------------------------- ### cloudImage(args) Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/content-components.md Creates a pre-configured block component for cloud-hosted images with automatic optimization. ```APIDOC ## cloudImage(args) ### Description Pre-configured block component for cloud-hosted images with automatic optimization. ### Parameters - **args.label** (string) - Required - Display name in toolbar ### Example ```typescript import { cloudImage } from '@keystatic/core/content-components'; const content = fields.document({ label: 'Content', componentBlocks: { image: cloudImage({ label: 'Image' }), }, }); ``` ``` -------------------------------- ### singleton(collection) Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Defines a singleton within a Keystatic configuration. Singletons represent unique, singular content entries like site settings or a homepage hero. ```APIDOC ## singleton(collection) ### Description Defines a singleton within a Keystatic configuration. Singletons represent unique, singular content entries (e.g., site settings, homepage hero). ### Parameters - **collection** (Singleton) - Required - Singleton configuration with label, schema, and optional format ### Returns Validated singleton object with type-checked schema. ``` -------------------------------- ### read() Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Reads a singleton entry. Returns the entry object if found, or null if it does not exist. ```APIDOC ## read(opts?: EntryReaderOpts) ### Description Reads the singleton entry. Returns null if the entry is not found. ### Parameters - **opts.resolveLinkedFiles** (boolean) - Optional - Resolve nested linked file content. ### Example ```typescript const settings = await reader.singletons.settings.read(); if (settings) { console.log(settings.siteName); } ``` ``` -------------------------------- ### Configure Keystatic Environment Variables Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/api-handler.md Required environment variables for GitHub storage mode in production deployments. ```bash # GitHub OAuth credentials KEYSTATIC_GITHUB_CLIENT_ID=your_github_app_client_id KEYSTATIC_GITHUB_CLIENT_SECRET=your_github_app_client_secret # Session encryption (any random string) KEYSTATIC_SECRET=super_secret_random_string_here ``` -------------------------------- ### Configure Entry Layout Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Sets the editor interface layout to either content-first or form-first. ```typescript entryLayout?: 'content' | 'form' ``` ```typescript collection({ label: 'Blog Posts', entryLayout: 'content', // ... }) ``` -------------------------------- ### createGitHubReader() Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Creates a reader instance for accessing content from a GitHub repository. ```APIDOC ## createGitHubReader() ### Description Initializes a reader to access content stored in a GitHub repository. ``` -------------------------------- ### Build-time Content Loading in Next.js Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Initializes a local reader and demonstrates usage within Next.js static generation functions. ```typescript // lib/keystatic.ts import { createReader } from '@keystatic/core/reader'; import config from '@/keystatic.config'; import path from 'path'; export const reader = createReader( path.join(process.cwd()), config ); // pages/blog/[slug].tsx import { reader } from '@/lib/keystatic'; export async function getStaticProps({ params }: { params: { slug: string } }) { const post = await reader.collections.posts.readOrThrow(params.slug); return { props: { post }, revalidate: 3600, }; } export async function getStaticPaths() { const slugs = await reader.collections.posts.list(); return { paths: slugs.map(slug => ({ params: { slug } })), fallback: 'blocking', }; } export default function PostPage({ post }: { post: Post }) { return
{post.title}
; } ``` -------------------------------- ### Configure GitHub storage Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Configuration schema for projects using GitHub as the content storage backend. ```typescript type GitHubConfig = { storage: { kind: 'github'; repo: RepoConfig; pathPrefix?: string; branchPrefix?: string; }; collections?: Collections; singletons?: Singletons; locale?: Locale; cloud?: { project: string }; ui?: UserInterface; } ``` -------------------------------- ### fields.select Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/form-fields.md Creates a dropdown selection field with predefined options. ```APIDOC ## fields.select(options) ### Description Creates a dropdown menu allowing users to select from a list of predefined options. ### Parameters - **label** (string) - Required - Field display name - **description** (string) - Optional - Helper text - **defaultValue** (string) - Optional - Initial selected value - **validation.isRequired** (boolean) - Optional - Whether selection is required - **options** (Array) - Required - Available choices (label/value pairs) ### Example ```typescript const status = fields.select({ label: 'Status', defaultValue: 'draft', options: [ { label: 'Draft', value: 'draft' }, { label: 'Published', value: 'published' }, { label: 'Archived', value: 'archived' }, ], }); ``` ``` -------------------------------- ### Mount Keystatic Admin in Astro Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Requires the client:load directive to ensure the component hydrates correctly in the browser. ```astro // src/pages/admin/[...params].astro --- import { Admin } from '@keystatic/core/ui'; import config from '@/keystatic.config'; --- ``` -------------------------------- ### Define UI Configuration Structure Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Defines the schema for customizing branding and navigation in the admin UI. ```typescript ui?: { brand?: { name: string; mark?: (props: { colorScheme: 'light' | 'dark' }) => ReactElement; }; navigation?: Navigation; } ``` -------------------------------- ### Read singleton entry or throw Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Method signature for reading a singleton entry, throwing an error if the entry does not exist. ```typescript readOrThrow(opts?: EntryReaderOpts): Promise ``` ```typescript const settings = await reader.singletons.settings.readOrThrow(); ``` -------------------------------- ### Define a basic singleton Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Configures a singleton entry with a label and a schema of fields. ```typescript singletons: { settings: singleton({ label: 'Site Settings', schema: { siteName: fields.text({ label: 'Site Name' }), tagline: fields.text({ label: 'Tagline' }), }, }), } ``` -------------------------------- ### Define the main Keystatic configuration object Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md The root configuration object for a Keystatic project, defining storage, collections, and UI settings. ```typescript type Config = { storage: LocalStorageConfig | GitHubStorageConfig | CloudStorageConfig; collections?: Collections; singletons?: Singletons; locale?: Locale; cloud?: { project: string }; ui?: UserInterface; } ``` -------------------------------- ### createGitHubReader Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Creates a reader instance for a GitHub repository. ```APIDOC ## createGitHubReader(config, options) ### Description Creates a reader instance for a GitHub repository, fetching content directly from the GitHub API. ### Parameters - **config** (Config) - Required - Keystatic configuration object - **options.repo** (string) - Required - GitHub repository in format `owner/repo` - **options.pathPrefix** (string) - Optional - Optional path prefix within repository - **options.ref** (string) - Optional - Git ref (branch, tag, commit SHA). Defaults to 'HEAD' - **options.token** (string) - Optional - GitHub personal access token for authentication ### Returns - **Reader** - Reader instance with typed access to collections and singletons. ### Throws - Error if GitHub API request fails - Error if ref does not exist - Error if token is invalid ``` -------------------------------- ### createReader Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Creates a reader instance for a local file system repository. ```APIDOC ## createReader(repoPath, config) ### Description Creates a reader instance for a local file system repository, providing typed access to collections and singletons. ### Parameters - **repoPath** (string) - Required - Absolute path to repository root - **config** (Config) - Required - Keystatic configuration object ### Returns - **Reader** - Reader instance with typed access to collections and singletons. ### Throws - Error if repository path does not exist - Error if configuration is invalid ``` -------------------------------- ### Read Content at Build Time Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Uses the Reader API to fetch collection entries or singleton data. Requires the project configuration and a valid file path. ```typescript import { createReader } from '@keystatic/core/reader'; import config from '@/keystatic.config'; import path from 'path'; const reader = createReader(path.join(process.cwd()), config); // Read single entry const post = await reader.collections.posts.read('my-post-slug'); // Read all entries const posts = await reader.collections.posts.all(); // Read singleton const settings = await reader.singletons.settings.read(); // With linked file resolution const post = await reader.collections.posts.read('my-post', { resolveLinkedFiles: true, }); ``` -------------------------------- ### Implement Typed Keystatic Configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Utilize the Config type for type-safe configuration and component initialization. ```typescript // For typed configuration import { Config } from '@keystatic/core'; const myConfig: Config = { /* ... */ }; // Component is fully typed // Type-safe ``` -------------------------------- ### Define GitHub storage configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Defines the structure and usage for GitHub-backed storage. ```typescript storage: { kind: 'github'; repo: { owner: string; name: string }; pathPrefix?: string; branchPrefix?: string; } ``` ```typescript export default config({ storage: { kind: 'github', repo: { owner: 'acme', name: 'website' }, pathPrefix: 'content', branchPrefix: 'keystatic-edit', }, collections: { /* ... */ }, }); ``` -------------------------------- ### Mount Keystatic Admin in Next.js App Router Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Requires 'use client' directive and dynamic rendering to function correctly within the App Router. ```typescript // app/admin/[[...params]]/page.tsx 'use client'; import { Admin } from '@keystatic/core/ui'; import config from '@/keystatic.config'; export const dynamic = 'force-dynamic'; // Disable static generation export default function KeystaticAdminPage() { return ; } ``` -------------------------------- ### createReader() Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Creates a reader instance for accessing content from the local file system. ```APIDOC ## createReader() ### Description Initializes a reader to access content stored in the local file system. ``` -------------------------------- ### config(config) Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Validates and returns a Keystatic configuration object. This function provides type inference for collections and singletons defined within the project. ```APIDOC ## config(config) ### Description Validates and returns a Keystatic configuration object. Provides type inference for collections and singletons. ### Parameters - **config** (Config) - Required - Configuration object with storage, collections, and singletons definitions ### Returns The same configuration object, type-checked and validated. ``` -------------------------------- ### Mount Keystatic Admin in Remix Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Implementation for Remix route files using the splat route pattern. ```typescript // routes/admin/$.tsx import { Admin } from '@keystatic/core/ui'; import config from '@/keystatic.config'; export default function AdminRoute() { return ; } ``` -------------------------------- ### Configure Keystatic Cloud storage Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Configuration schema for projects utilizing the Keystatic Cloud storage backend. ```typescript type CloudConfig = { storage: { kind: 'cloud'; pathPrefix?: string; branchPrefix?: string; }; cloud: { project: string }; collections?: Collections; singletons?: Singletons; locale?: Locale; ui?: UserInterface; } ``` -------------------------------- ### Exported members from @keystatic/core Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/STRUCTURE.md Core configuration and field definitions available from the main package. ```typescript config, collection, singleton Fields: text, slug, integer, number, date, datetime, checkbox, select, multiselect, url, image, file, document, array, object, conditional, relationship, multiRelationship, blocks ``` -------------------------------- ### Define cloud storage configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Defines the structure and usage for Keystatic Cloud storage. ```typescript storage: { kind: 'cloud'; pathPrefix?: string; branchPrefix?: string; } cloud: { project: string; } ``` ```typescript export default config({ storage: { kind: 'cloud', pathPrefix: 'content', }, cloud: { project: 'your-project-id', }, collections: { /* ... */ }, }); ``` -------------------------------- ### Configure Keystatic for Next.js Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Defines the storage provider and content collections for a Keystatic project. This configuration is compatible with Next.js, Remix, and Astro. ```typescript // keystatic.config.ts import { config, collection, singleton, fields } from '@keystatic/core'; export default config({ storage: { kind: 'github', repo: { owner: 'acme', name: 'website' }, }, collections: { posts: collection({ label: 'Blog Posts', slugField: 'slug', schema: { title: fields.text({ label: 'Title' }), slug: fields.slug({ label: 'Slug' }), content: fields.document({ label: 'Content' }), }, }), }, }); ``` -------------------------------- ### Usage: Read Entry or Throw Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Retrieve an entry and handle potential missing entries via try-catch. ```typescript try { const post = await reader.collections.posts.readOrThrow('my-post'); console.log(post.title); } catch (error) { console.error('Post not found:', error); } ``` -------------------------------- ### Define Locale Configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Sets the default language for the Keystatic admin interface. ```typescript locale?: Locale ``` ```typescript export default config({ locale: 'es', storage: { kind: 'local' }, collections: { /* ... */ }, }); ``` -------------------------------- ### Integrate with Remix Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/api-handler.md Implementation of the Keystatic API handler within a Remix route file using loader and action functions. ```typescript // routes/api/keystatic/$.tsx import { json, type LoaderFunction } from '@remix-run/node'; import { makeGenericAPIRouteHandler } from '@keystatic/core/api/generic'; import config from '@/keystatic.config'; const handler = makeGenericAPIRouteHandler({ config, clientId: process.env.KEYSTATIC_GITHUB_CLIENT_ID, clientSecret: process.env.KEYSTATIC_GITHUB_CLIENT_SECRET, secret: process.env.KEYSTATIC_SECRET, }); export const loader: LoaderFunction = async ({ request }) => { const keystatic = await handler({ method: request.method, headers: Object.fromEntries(request.headers), url: request.url, body: await request.text(), }); return new Response(keystatic.body, { status: keystatic.status, headers: keystatic.headers, }); }; export const action = loader; ``` -------------------------------- ### Define Keystatic Configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md A complete configuration object defining storage, UI, collections, and singletons for a Keystatic project. ```typescript import { config, collection, singleton, fields } from '@keystatic/core'; export default config({ // Storage configuration storage: { kind: 'github', repo: { owner: 'acme', name: 'website' }, pathPrefix: 'content', branchPrefix: 'edit-', }, // Localization locale: 'en', // UI Customization ui: { brand: { name: 'Acme CMS', mark: ({ colorScheme }) => ( {colorScheme === 'light' ? '🏢' : '🌙'} ), }, navigation: { 'Content': ['posts', 'pages'], 'Taxonomies': ['categories', 'tags'], 'Settings': ['siteConfig', 'navigation'], }, }, // Collections collections: { posts: collection({ label: 'Blog Posts', path: 'blog/posts/**', format: { data: 'yaml', contentField: 'content' }, entryLayout: 'content', slugField: 'slug', previewUrl: 'https://acme.com/blog/{slug}', columns: ['title', 'date', 'status'], schema: { title: fields.text({ label: 'Title', validation: { isRequired: true }, }), slug: fields.slug({ label: 'URL Slug' }), date: fields.date({ label: 'Published Date', defaultValue: { kind: 'today' }, }), status: fields.select({ label: 'Status', options: [ { label: 'Draft', value: 'draft' }, { label: 'Published', value: 'published' }, ], defaultValue: 'draft', }), author: fields.relationship({ label: 'Author', collection: 'authors', validation: { isRequired: true }, }), tags: fields.multiRelationship({ label: 'Tags', collection: 'tags', }), content: fields.document({ label: 'Content', formatting: { headingLevels: [1, 2, 3], inlineMarks: ['bold', 'italic', 'code'], }, dividers: true, images: { directory: 'blog-images' }, }), }, }), pages: collection({ label: 'Pages', path: 'pages/*', format: 'json', entryLayout: 'form', slugField: 'slug', schema: { title: fields.text({ label: 'Title' }), slug: fields.slug({ label: 'Slug' }), content: fields.document({ label: 'Content' }), }, }), authors: collection({ label: 'Authors', path: 'authors/*', format: 'json', entryLayout: 'form', slugField: 'slug', schema: { name: fields.text({ label: 'Name' }), slug: fields.slug({ label: 'Slug' }), email: fields.text({ label: 'Email' }), bio: fields.text({ label: 'Bio', multiline: true }), avatar: fields.image({ label: 'Avatar' }), }, }), tags: collection({ label: 'Tags', path: 'tags/*', format: 'json', entryLayout: 'form', slugField: 'slug', schema: { name: fields.text({ label: 'Name' }), slug: fields.slug({ label: 'Slug' }), description: fields.text({ label: 'Description' }), }, }), }, // Singletons singletons: { siteConfig: singleton({ label: 'Site Configuration', path: 'config/site', format: 'json', schema: { siteName: fields.text({ label: 'Site Name' }), siteDescription: fields.text({ label: 'Description' }), siteUrl: fields.url({ label: 'Site URL' }), sitemapChangeFrequency: fields.select({ label: 'Sitemap Change Frequency', options: [ { label: 'Daily', value: 'daily' }, { label: 'Weekly', value: 'weekly' }, { label: 'Monthly', value: 'monthly' }, ], }), }, }), navigation: singleton({ label: 'Navigation', path: 'config/navigation', format: 'json', schema: { items: fields.array( fields.object({ fields: { label: fields.text({ label: 'Label' }), url: fields.url({ label: 'URL' }), children: fields.array( fields.object({ fields: { label: fields.text({ label: 'Label' }), url: fields.url({ label: 'URL' }), }, }), { label: 'Submenu Items' } ), }, }), { label: 'Navigation Items' } ), }, }), }, }); ``` -------------------------------- ### Initialize and Access Reader Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Create a reader instance and access collections or singletons with type safety. ```typescript const reader = createReader(process.cwd(), config); // Type-safe collection access const postReader: CollectionReader = reader.collections.posts; // Type-safe singleton access const settingsReader: SingletonReader = reader.singletons.settings; ``` -------------------------------- ### Configure Admin Brand Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Customizes the site name and logo component, supporting light and dark mode variants. ```typescript ui: { brand: { name: 'Acme CMS', mark: ({ colorScheme }) => ( Acme ), }, } ``` -------------------------------- ### Syntax Highlighting for Code Blocks Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/renderer.md Integrate prism-react-renderer to provide syntax highlighting for code blocks. ```typescript import { highlight } from 'prism-react-renderer'; const customRenderers: Renderers = { inline: defaultRenderers.inline, block: { ...defaultRenderers.block, code: ({ children, language = 'plaintext' }) => { const tokens = highlight(children, language); return (
          
            {tokens.map((token, i) => (
              
                {token.content}
              
            ))}
          
        
); }, }, }; ``` -------------------------------- ### Lazy-load Keystatic Admin with Next.js dynamic Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Use dynamic imports to lazy-load the Admin component and disable SSR to prevent hydration issues. ```typescript // pages/admin/[[...params]].tsx import dynamic from 'next/dynamic'; import config from '@/keystatic.config'; const Admin = dynamic( () => import('@keystatic/core/ui').then(mod => mod.Admin), { ssr: false } ); export default function AdminPage() { return ; } ``` -------------------------------- ### readOrThrow() Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Reads a singleton entry. Returns the entry object if found, or throws an error if it does not exist. ```APIDOC ## readOrThrow(opts?: EntryReaderOpts) ### Description Read the singleton entry. Throws an error if the entry does not exist. ### Parameters - **opts.resolveLinkedFiles** (boolean) - Optional - Resolve nested linked file content. ### Example ```typescript const settings = await reader.singletons.settings.readOrThrow(); ``` ``` -------------------------------- ### Define local storage configuration Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Defines the structure and usage for local file system storage, intended for development and testing. ```typescript storage: { kind: 'local'; } ``` ```typescript export default config({ storage: { kind: 'local' }, collections: { /* ... */ }, }); ``` -------------------------------- ### object(options) Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/form-fields.md Creates a composite field containing multiple named fields. ```APIDOC ## object(options) ### Description Composite field containing multiple named fields. ### Parameters - **label** (string) - Optional - Field group label - **fields** (Record) - Required - Named field definitions - **layout** ('form' | 'block') - Optional - UI layout ### Example ```typescript const author = fields.object({ label: 'Author', fields: { name: fields.text({ label: 'Name' }), email: fields.text({ label: 'Email' }), bio: fields.text({ label: 'Bio', multiline: true }), }, }); ``` ``` -------------------------------- ### Render Keystatic Documents Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Use DocumentRenderer to display content, optionally overriding default renderers for custom styling. ```typescript import { defaultRenderers } from '@keystatic/core/renderer'; export function BlogPost({ content }) { return (
); } // Or customize renderers: const customRenderers = { ...defaultRenderers, block: { ...defaultRenderers.block, heading: ({ level, children }) => (

{children}

), }, }; ``` -------------------------------- ### Development Mode Missing Configuration Error Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/api-handler.md The error message displayed in development mode when required configuration is missing. ```text Missing required config in Keystatic API setup when using the 'github' storage mode: - clientId (can be provided via KEYSTATIC_GITHUB_CLIENT_ID env var) - clientSecret (can be provided via KEYSTATIC_GITHUB_CLIENT_SECRET env var) - secret (can be provided via KEYSTATIC_SECRET env var) ``` -------------------------------- ### Mount Keystatic Admin in Next.js Pages Router Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/ui-exports.md Standard implementation for the Pages Router directory structure. ```typescript // pages/admin/[[...params]].tsx import { Admin } from '@keystatic/core/ui'; import config from '@/keystatic.config'; export default function KeystaticAdminPage() { return ; } ``` -------------------------------- ### Configure Collection Path Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/configuration.md Defines the file system path pattern for entries using glob syntax. ```typescript path?: `${string}/${Glob}` | `${string}/${Glob}/${string}` ``` ```typescript // Flat: content/posts/{slug}.md path: 'content/posts/*' // Nested: content/blog/2024/06/{slug}.md path: 'content/blog/**' // Custom subdirectories: content/posts/{slug}/index.md path: 'content/posts/{slug}' // Template: content/*/articles/*' path: 'content/*/articles/*' ``` -------------------------------- ### Integrate Keystatic with Next.js App Router Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Configure the admin page and API route handler for Next.js applications. ```typescript // app/admin/[[...params]]/page.tsx 'use client'; import { Admin } from '@keystatic/core/ui'; import config from '@/keystatic.config'; export default function AdminPage() { return ; } ``` ```typescript // app/api/keystatic/[...params]/route.ts import { makeGenericAPIRouteHandler } from '@keystatic/core/api/generic'; import config from '@/keystatic.config'; const handler = makeGenericAPIRouteHandler({ config, clientId: process.env.KEYSTATIC_GITHUB_CLIENT_ID, clientSecret: process.env.KEYSTATIC_GITHUB_CLIENT_SECRET, secret: process.env.KEYSTATIC_SECRET, }); export const GET = handler; export const POST = handler; ``` -------------------------------- ### Define a singleton Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Creates a unique, singular content entry definition. ```typescript import { singleton, fields } from '@keystatic/core'; const settings = singleton({ label: 'Site Settings', path: 'config/settings', format: 'json', schema: { siteName: fields.text({ label: 'Site Name' }), siteDescription: fields.text({ label: 'Description' }), socialLinks: fields.object({ fields: { twitter: fields.url({ label: 'Twitter URL' }), github: fields.url({ label: 'GitHub URL' }), }, }), }, }); ``` -------------------------------- ### Configure and Render Document Field Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/renderer.md Defines the document field schema with specific formatting options and demonstrates rendering the content using DocumentRenderer. ```typescript import { fields } from '@keystatic/core'; import { defaultRenderers } from '@keystatic/core/renderer'; // In schema: const blogPost = collection({ // ... schema: { content: fields.document({ label: 'Content', // Configure which block types are available formatting: { inlineMarks: ['bold', 'italic', 'code'], headingLevels: [1, 2, 3], }, dividers: true, links: true, images: true, tables: true, }), }, }); // When rendering: import { reader } from '@/lib/keystatic'; export async function getStaticProps() { const post = await reader.collections.posts.read('my-post'); return { props: { post } }; } export default function Page({ post }) { return (

{post.title}

); } ``` -------------------------------- ### EntryLayout Type Definition Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/configuration.md Defines the available editor UI layouts. ```typescript type EntryLayout = 'content' | 'form' ``` -------------------------------- ### Read Entry or Throw Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Signature for reading an entry that throws an error if not found. ```typescript readOrThrow(slug: string, opts?: EntryReaderOpts): Promise ``` -------------------------------- ### Define GitHub Storage in Config Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/README.md Configuration object for enabling GitHub storage in your Keystatic config file. ```typescript storage: { kind: 'github', repo: { owner: 'your-org', name: 'your-repo' }, } ``` -------------------------------- ### Read All Entries Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/reader.md Signature for retrieving all entries in a collection. ```typescript all(opts?: EntryReaderOpts): Promise> ``` -------------------------------- ### Integrate Keystatic with Astro Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/api-handler.md Uses the generic API handler to manage Keystatic routes within an Astro API route file. ```typescript // src/pages/api/keystatic/[...params].ts import { makeGenericAPIRouteHandler } from '@keystatic/core/api/generic'; import type { APIRoute } from 'astro'; import config from '@/keystatic.config'; const handler = makeGenericAPIRouteHandler({ config, clientId: import.meta.env.KEYSTATIC_GITHUB_CLIENT_ID, clientSecret: import.meta.env.KEYSTATIC_GITHUB_CLIENT_SECRET, secret: import.meta.env.KEYSTATIC_SECRET, }); export const GET: APIRoute = async ({ request }) => { const keystatic = await handler({ method: request.method, headers: Object.fromEntries(request.headers), url: request.url, body: await request.text(), }); return new Response(keystatic.body, { status: keystatic.status, headers: keystatic.headers, }); }; export const POST = GET; ``` -------------------------------- ### file Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/form-fields.md Defines a single file asset field that returns a relative path. ```APIDOC ## file ### Description Creates a single file asset field for file uploads. ### Signature `fields.file(options: { label: string, description?: string, directory?: string, validation?: { isRequired?: boolean } }): AssetFormField` ### Parameters - **label** (string) - Required - Field display name - **description** (string) - Optional - Helper text - **directory** (string) - Optional - Subdirectory for files (default: 'assets') - **validation.isRequired** (boolean) - Optional - Whether file is required ### Returns Relative path to file. ### Example ```typescript const pdf = fields.file({ label: 'PDF Document', directory: 'assets/documents', }); ``` ``` -------------------------------- ### fields.datetime Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/api-reference/form-fields.md Creates a date and time picker field that returns an ISO 8601 string. ```APIDOC ## fields.datetime(options) ### Description Creates a date and time picker field for selecting specific timestamps. ### Parameters - **label** (string) - Required - Field display name - **description** (string) - Optional - Helper text - **defaultValue** (string | { kind: 'now' }) - Optional - Initial value or 'now' - **validation.isRequired** (boolean) - Optional - Whether value is required - **validation.min** (string) - Optional - Earliest allowed datetime - **validation.max** (string) - Optional - Latest allowed datetime ### Example ```typescript const createdAt = fields.datetime({ label: 'Created At', defaultValue: { kind: 'now' }, validation: { isRequired: true }, }); ``` ``` -------------------------------- ### Exported members from @keystatic/core/api/generic Source: https://github.com/thinkmill/keystatic/blob/main/_autodocs/STRUCTURE.md Generic API route handling utilities. ```typescript makeGenericAPIRouteHandler, APIRouteConfig ```