Build content-heavy sites with Git-backed TinaCMS. Provides visual editing for blogs, documentation, and marketing sites. Supports Next.js, Vite+React, and Astro with self-hosting options. Use when setting up CMS with non-technical editors or troubleshooting ESbuild compilation, module resolution, or Docker binding issues.
View on GitHubSelect agents to install to:
npx add-skill https://github.com/jezweb/claude-skills/blob/main/skills/tinacms/SKILL.md -a claude-code --skill tinacmsInstallation paths:
.claude/skills/tinacms/# TinaCMS
Git-backed headless CMS with visual editing for content-heavy sites.
**Last Updated**: 2026-01-09
**Versions**: tinacms@3.2.0, @tinacms/cli@2.0.7
---
## Quick Start
```bash
# Initialize TinaCMS
npx @tinacms/cli@latest init
# Update package.json scripts
{
"dev": "tinacms dev -c \"next dev\"",
"build": "tinacms build && next build"
}
# Set environment variables
NEXT_PUBLIC_TINA_CLIENT_ID=your_client_id
TINA_TOKEN=your_read_only_token
# Start dev server
npm run dev
# Access admin interface
http://localhost:3000/admin/index.html
```
---
## Next.js Integration
**useTina Hook** (enables visual editing):
```tsx
import { useTina } from 'tinacms/dist/react'
import { client } from '../../tina/__generated__/client'
export default function BlogPost(props) {
const { data } = useTina({
query: props.query,
variables: props.variables,
data: props.data
})
return <article><h1>{data.post.title}</h1></article>
}
export async function getStaticProps({ params }) {
const response = await client.queries.post({
relativePath: `${params.slug}.md`
})
return {
props: {
data: response.data,
query: response.query,
variables: response.variables
}
}
}
```
**App Router**: Admin route at `app/admin/[[...index]]/page.tsx`
**Pages Router**: Admin route at `pages/admin/[[...index]].tsx`
---
## Schema Configuration
**tina/config.ts** structure:
```typescript
import { defineConfig } from 'tinacms'
export default defineConfig({
branch: process.env.GITHUB_BRANCH || 'main',
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,
token: process.env.TINA_TOKEN,
build: {
outputFolder: 'admin',
publicFolder: 'public',
},
schema: {
collections: [/* ... */],
},
})
```
**Collection Example** (Blog Post):
```typescript
{
name: 'post', // Alphanumeric + underscores only
label: 'Blog Posts',
path: 'content/posts', // No trailing slash
format: 'mdx',
fields: [
{
type: 'string',