tinacms
Complete TinaCMS skill for building content-heavy sites with Git-backed CMS. Use this skill when setting up blogs, documentation sites, or marketing sites that require visual editing and content management for non-technical users. Supports Next.js (App Router + Pages Router), Vite + React, Astro, and framework-agnostic setups. Prevents 9+ common errors including ESbuild compilation issues, module resolution problems, schema configuration errors, Docker binding issues, and deployment problems. Self-hosting options for Cloudflare Workers, Vercel Functions, and Netlify Functions included. Keywords: TinaCMS, Tina CMS, Git-backed CMS, visual editing CMS, content management, Next.js CMS, App Router TinaCMS, Pages Router TinaCMS, Vite React TinaCMS, Astro TinaCMS, framework-agnostic CMS, TinaCloud, self-hosted TinaCMS, blog CMS, documentation site CMS, marketing site CMS, GraphQL CMS, tina schema, tina collections, tina templates, tinacli, @tinacms/cli, ESbuild compilation error, module resolution tina, schema configuration, Docker binding issues, Cloudflare Workers TinaCMS, Vercel Functions TinaCMS, Netlify Functions TinaCMS
What this skill does
# TinaCMS Skill
Complete skill for integrating TinaCMS into modern web applications.
---
## What is TinaCMS?
**TinaCMS** is an open-source, Git-backed headless content management system (CMS) that enables developers and content creators to collaborate seamlessly on content-heavy websites.
### Key Features
1. **Git-Backed Storage**
- Content stored as Markdown, MDX, or JSON files in Git repository
- Full version control and change history
- No vendor lock-in - content lives in your repo
2. **Visual/Contextual Editing**
- Side-by-side editing experience
- Live preview of changes as you type
- WYSIWYG-like editing for Markdown content
3. **Schema-Driven Content Modeling**
- Define content structure in code (`tina/config.ts`)
- Type-safe GraphQL API auto-generated from schema
- Collections and fields system for organized content
4. **Flexible Deployment**
- **TinaCloud**: Managed service (easiest, free tier available)
- **Self-Hosted**: Cloudflare Workers, Vercel Functions, Netlify Functions, AWS Lambda
- Multiple authentication options (Auth.js, custom, local dev)
5. **Framework Support**
- **Best**: Next.js (App Router + Pages Router)
- **Good**: React, Astro (experimental visual editing), Gatsby, Hugo, Jekyll, Remix, 11ty
- **Framework-Agnostic**: Works with any framework (visual editing limited to React)
### Current Versions
- **tinacms**: 2.9.0 (September 2025)
- **@tinacms/cli**: 1.11.0 (October 2025)
- **React Support**: 19.x (>=18.3.1 <20.0.0)
---
## When to Use This Skill
### ✅ Use TinaCMS When:
1. **Building Content-Heavy Sites**
- Blogs and personal websites
- Documentation sites
- Marketing websites
- Portfolio sites
2. **Non-Technical Editors Need Access**
- Content teams without coding knowledge
- Marketing teams managing pages
- Authors writing blog posts
3. **Git-Based Workflow Desired**
- Want content versioning through Git
- Need content review through pull requests
- Prefer content in repository with code
4. **Visual Editing Required**
- Editors want to see changes live
- WYSIWYG experience preferred
- Side-by-side editing workflow
### ❌ Don't Use TinaCMS When:
1. **Real-Time Collaboration Needed**
- Multiple users editing simultaneously (Google Docs-style)
- Use Sanity, Contentful, or Firebase instead
2. **Highly Dynamic Data**
- E-commerce product catalogs with frequent inventory changes
- Real-time dashboards
- Use traditional databases (D1, PostgreSQL) instead
3. **No Content Management Needed**
- Application is data-driven, not content-driven
- Hard-coded content is sufficient
---
## Setup Patterns by Framework
Use the appropriate setup pattern based on your framework choice.
### 1. Next.js Setup (Recommended)
#### App Router (Next.js 13+)
**Steps:**
1. **Initialize TinaCMS:**
```bash
npx @tinacms/cli@latest init
```
- When prompted for public assets directory, enter `public`
2. **Update package.json scripts:**
```json
{
"scripts": {
"dev": "tinacms dev -c \"next dev\"",
"build": "tinacms build && next build",
"start": "tinacms build && next start"
}
}
```
3. **Set environment variables:**
```env
# .env.local
NEXT_PUBLIC_TINA_CLIENT_ID=your_client_id
TINA_TOKEN=your_read_only_token
```
4. **Start development server:**
```bash
npm run dev
```
5. **Access admin interface:**
```
http://localhost:3000/admin/index.html
```
**Key Files Created:**
- `tina/config.ts` - Schema configuration
- `app/admin/[[...index]]/page.tsx` - Admin UI route (if using App Router)
**Template**: See `templates/nextjs/tina-config-app-router.ts`
---
#### Pages Router (Next.js 12 and below)
**Setup is identical**, except admin route is:
- `pages/admin/[[...index]].tsx` instead of app directory
**Data Fetching Pattern:**
```tsx
// pages/posts/[slug].tsx
import { client } from '../../tina/__generated__/client'
import { useTina } from 'tinacms/dist/react'
export default function BlogPost(props) {
// Hydrate for visual editing
const { data } = useTina({
query: props.query,
variables: props.variables,
data: props.data
})
return (
<article>
<h1>{data.post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: data.post.body }} />
</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
}
}
}
export async function getStaticPaths() {
const response = await client.queries.postConnection()
const paths = response.data.postConnection.edges.map((edge) => ({
params: { slug: edge.node._sys.filename }
}))
return { paths, fallback: 'blocking' }
}
```
**Template**: See `templates/nextjs/tina-config-pages-router.ts`
---
### 2. Vite + React Setup
**Steps:**
1. **Install dependencies:**
```bash
npm install react@^19 react-dom@^19 tinacms
```
2. **Initialize TinaCMS:**
```bash
npx @tinacms/cli@latest init
```
- Set public assets directory to `public`
3. **Update vite.config.ts:**
```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 3000 // TinaCMS default
}
})
```
4. **Update package.json scripts:**
```json
{
"scripts": {
"dev": "tinacms dev -c \"vite\"",
"build": "tinacms build && vite build",
"preview": "vite preview"
}
}
```
5. **Create admin interface:**
**Option A: Manual route (React Router)**
```tsx
// src/pages/Admin.tsx
import TinaCMS from 'tinacms'
export default function Admin() {
return <div id="tina-admin" />
}
```
**Option B: Direct HTML**
```html
<!-- public/admin/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Tina CMS</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/@fs/[path-to-tina-admin]"></script>
</body>
</html>
```
6. **Use useTina hook for visual editing:**
```tsx
import { useTina } from 'tinacms/dist/react'
import { client } from '../tina/__generated__/client'
function BlogPost({ initialData }) {
const { data } = useTina({
query: initialData.query,
variables: initialData.variables,
data: initialData.data
})
return (
<article>
<h1>{data.post.title}</h1>
<div>{/* render body */}</div>
</article>
)
}
```
7. **Set environment variables:**
```env
# .env
VITE_TINA_CLIENT_ID=your_client_id
VITE_TINA_TOKEN=your_read_only_token
```
**Template**: See `templates/vite-react/`
---
### 3. Astro Setup
**Steps:**
1. **Use official starter (recommended):**
```bash
npx create-tina-app@latest --template tina-astro-starter
```
**Or initialize manually:**
```bash
npx @tinacms/cli@latest init
```
2. **Update package.json scripts:**
```json
{
"scripts": {
"dev": "tinacms dev -c \"astro dev\"",
"build": "tinacms build && astro build",
"preview": "astro preview"
}
}
```
3. **Configure Astro:**
```javascript
// astro.config.mjs
import { defineConfig } from 'astro/config'
import react from '@astro/react'
export default defineConfig({
integrations: [react()] // Required for Tina admin
})
```
4. **Visual editing (experimental):**
- Requires React components
- Use `client:tinaDirective` for interactive editing
- Full visual editing is experimental as of October 2025
5. **Set environment variables:**
```env
# .env
PUBLRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.