tinacms
Git-backed headless CMS that gives React apps live, in-context Markdown editing and a generated GraphQL content API.
Repository Health
Technical Analysis
TinaCMS is an open-source, Git-native headless CMS. Content lives as Markdown, MDX, JSON, or YAML files directly in your own GitHub repository — there’s no external content database — and a GraphQL API is generated from your schema so pages can query it like post.author.firstName.
What sets it apart is its live, in-context visual editing: the useTina() hook and TinaCMSProvider2 component swap in editable data only when a page is loaded inside Tina’s admin, so editors click directly on the rendered page to change copy, and every save lands as a normal Git commit. It ships as a full self-hosted admin UI or can be paired with TinaCloud for hosted auth and media.
What You Get
- A GraphQL API auto-generated from your content schema, so Markdown/MDX/JSON/YAML front matter can be queried like
post.author.firstName - A drop-in
useTina()hook andTinaCMSProvider2component that swap production data for live, editable data only when the page loads inside Tina’s admin - A full self-hosted or TinaCloud-backed admin UI at
/admin, with a Plate.js rich-text editor, drag-and-drop array fields, and a branch-switcher plugin for Git-based editorial workflows - PKCE-based OAuth authentication against TinaCloud or a custom auth provider, plus a pluggable form/field/screen system inherited from
@tinacms/toolkit
Common Use Cases
- Adding an editable content layer to an existing Next.js, Astro, or Hugo static site without migrating content out of the Git repo
- Letting non-technical editors visually edit Markdown/MDX pages in place, with changes committed back to GitHub
- Building a documentation or marketing site where content authors need a GraphQL query layer over structured Markdown collections
- Standing up a fully self-hosted CMS admin, with no TinaCloud dependency, for teams that must keep content infrastructure in-house
Under The Hood
Architecture
The tinacms package sits atop the monorepo’s @tinacms/toolkit (packages/tinacms/src/toolkit), a plugin-based CMS engine for forms, fields, sidebar screens, and alerts, which the top-level TinaCMSProvider (src/tina-cms.tsx) wraps in a React context provider alongside an error boundary, an internal GraphQL client (src/internalClient), and a PKCE-based auth layer (src/auth) for TinaCloud or a self-hosted backend. Content queries flow through useTina() (src/react.tsx), which hashes the query/variables pair, attaches Tina’s metadata for the visual quick-edit overlay, and rehydrates returned data with edit hooks when the page runs inside Tina’s admin iframe. The admin surface (src/admin) is a separate React Router app (RouteMappingPlugin, TinaAdminApi) mounted at /admin, talking to the same GraphQL backend, so schema changes ripple from @tinacms/schema-tools validation through generated GraphQL types into both the editing UI and the public site’s data layer.
Tech Stack
Written in TypeScript (strict mode disabled in the shared base.tsconfig.json) targeting ESNext with bundler-based module resolution, the package pairs a large React surface (Radix UI primitives, @ariakit/react, @dnd-kit for drag/drop reordering) with a Plate.js-based (@udecode/plate*) rich-text/MDX editor, its own GraphQL client (graphql, graphql-tag, @graphql-inspector/core), Zod/Yup for runtime schema validation, final-form for form state, and internal @tinacms/* workspace packages (schema-tools, mdx, search, bridge) built with Turborepo. Peer dependencies are limited to react/react-dom, and internal build tooling compiles multiple entry points (client, react, admin, rich-text) into separate dist bundles for tree-shaking.
Code Quality
The package ships extensive Vitest coverage (dozens of test files, including react.test.tsx, auth/pkce.test.ts, and internalClient/index.test.ts) run under happy-dom with React Testing Library, testing the GraphQL client, PKCE auth flow, and caching layer directly rather than relying only on end-to-end coverage — which lives separately in the monorepo’s Playwright suites, run across a wide set of CI workflows covering per-framework kitchen-sink tests (Next.js, Astro, Hugo), CodeQL scanning, and dependency review. Linting/formatting is enforced with Biome across packages and examples, and a changesets-based release process gates merges on version-bump metadata; TypeScript strict mode is explicitly off, so type coverage is present but not maximally enforced.
API Design
The public API centers on one hook, useTina(), and one provider, TinaCMSProvider2 (the default export), that let a site keep rendering static GraphQL-fetched data in production while transparently swapping in live, click-to-edit data when the page loads inside Tina’s admin — no separate editor mode to wire up by hand. Getting started is a single npx create-tina-app@latest scaffold, and schema types (Config, Collection, Template, TinaField) are re-exported from @tinacms/schema-tools, with deprecated aliases kept for backward compatibility rather than shipped as hard breaking changes.