Component Demo
A live demo of Keystatic-supported MDX components, including structured tabs, layouts, media, code blocks, timelines, and callouts.
This post exercises the structured, editor-supported MDX APIs. Use it as a round-trip fixture and a visual reference for component props and authored children.
Admonitions
Information
This is an info admonition. Use it for helpful context, tips, and neutral information the reader should be aware of.
Watch Out
This is a warning admonition. Use it when something could go wrong, or when the reader needs to proceed with caution.
Danger Zone
This is a danger admonition. Use it for destructive actions, breaking changes, or things that will cause problems if ignored.
Well Done
This is a success admonition. Use it to confirm something worked, or to highlight a positive outcome.
Steps
Create the component. Add a new
.astrofile insrc/components/with the component’s template and logic.Define the Props interface. Export a TypeScript interface so the component is type-safe when used in MDX.
Wire it into Keystatic. Create a matching component block in the Keystatic admin project so the editor knows about its schema.
Use it in content. Insert the component without a manual import; Astro’s manifest-backed MDX pipeline supplies editor-supported imports.
Accordion
What is Keystatic?
Keystatic is a CMS that treats your content as files on disk — Markdown, MDX, YAML, JSON — rather than rows in a database. You get a rich editing UI that writes directly to your content repo, with no API layer between the editor and your files.
Why use MDX instead of plain Markdown?
MDX lets you import and use components directly in your Markdown files. This means you can create rich, interactive content — tabs, accordions, code comparisons, terminal windows — without leaving the Markdown authoring experience.
How do I add a new component?
Create a component block definition in the Keystatic admin project (one file
per component, ~20 lines each), add it to the mdxComponents map, rebuild,
and it appears in the editor toolbar immediately.
Tabs
npm
npm install @keystatic/corepnpm
pnpm add @keystatic/coreyarn
yarn add @keystatic/corePros & Cons
Pros
- Files on disk — works with git, no database migrations
- Type-safe schema — TypeScript-powered field definitions
- Local-first — no cloud dependency for the editing experience
- Component blocks — rich MDX editing with custom React previews
Cons
- Needs a running dev server (Vite) for the editing UI
- Component schemas must be kept in sync manually
- No built-in auth in local mode (needs a reverse proxy with basic auth)
- Image handling requires the site repo for optimized imports
Side by Side
The SideBySide component puts text alongside media. On desktop, the two panels sit next to each other. On mobile, they stack vertically — no media query needed, it’s built into the component.
With the reverse prop, the media appears on the left and the text on the right. This is useful for alternating layouts in a long article — it keeps the visual rhythm from becoming monotonous.
Image Grid
Figure
File Tree
src
pages
components
styles
Keyboard Input
Press Ctrl + K to open search, then press Escape to close it.
Responsive Table
| Component | Authoring shape | No-JS behavior |
|---|---|---|
| Tabs | Repeating TabItem children | Labeled stacked sections |
| Timeline | Dated TimelineItem children | Readable ordered history |
Content Grid
Nested content
Grid items can contain editor-supported components.
Keystatic documentation
Schema-driven content editing for Markdown, MDX, YAML, and JSON.
keystatic.comA two-column spanning item demonstrates responsive span behavior without exposing arbitrary CSS classes to editors.
Full-width content remains readable when the grid collapses on narrow screens.
API Endpoint
/api/users/api/users/api/users/:id/api/users/:id/api/users/:idTerminal Window
Code Compare
const fs = require('fs');\nconst data = fs.readFileSync('./config.json', 'utf8');\nconst config = JSON.parse(data);\nconsole.log(config.port);import { readFile } from 'node:fs/promises';\n\nconst data = await readFile('./config.json', 'utf8');\nconst config = JSON.parse(data) as Config;\nconsole.log(config.port);Case Study Header
Case Study
Cloud Migration: Bare Metal to k3s
The Problem
A homelab running 15 Docker containers on a single Ubuntu server had no orchestration, no auto-restart on failure, and manual TLS certificate renewal. Every update required SSH + docker-compose down/up with downtime.
The Result
Migrated to a 3-node k3s cluster with Traefik ingress, cert-manager for automatic TLS, Longhorn for replicated storage, and GitOps via Flux. Zero-downtime deployments, automatic failover, and a 40% reduction in manual maintenance hours.
Video Embed
GitHub Repo Card
The web framework for content-driven websites. ⭐️ Star to support our work!
First class CMS experience, TypeScript API, Markdown & YAML/JSON based, no DB
Pull Quote
The best code is the code you don’t write. Every line you don’t write is a line you don’t have to debug, test, or maintain.
Stat Blocks
Link Card
Keystatic
First-class CMS experience, TypeScript API, Markdown & YAML/JSON based, no database.
keystatic.devAstro
The web framework for content-driven websites. Zero JS by default, opt-in to interactivity.
astro.buildAside
Timeline
First commit. A single Ubuntu server running Docker Compose with Traefik as a reverse proxy.
Added Ansible for configuration management. Playbooks replaced shell scripts.
Migrated to a 3-node k3s cluster. GitOps with Flux, cert-manager for TLS, Longhorn for storage.
Added monitoring with Prometheus + Grafana. Alerting via ntfy.sh push notifications.
Keystatic admin panel deployed. Content authoring moved from hand-writing MDX to a rich editing UI.
Carousel
Animate
This paragraph slides up into view when you scroll to it. The Animate
component supports presets like fade, slide-up, zoom-focus, and
stagger-grid. Apply it around any content you want to reveal on scroll.
A second animation block with a fade effect and a longer delay. Multiple
Animate blocks can be chained to create sequenced reveals down the page.
Reveal
The Reveal component is a lighter alternative — pure CSS scroll-driven animation with no JavaScript. Use it for subtle content reveals that don’t need the full motion engine.