nextjs-tinacms
Next.js 16 + React 19 + TinaCMS + Vercel
Opinionated for: Next.js App Router + TinaCMS + Tina Cloud + Vercel + Tailwind CSS 4 + shadcn/ui.
Two workflows: New Project (scaffold from scratch) or Add CMS (integrate into existing Next.js 15/16 project).
Stack
| Technology | Version | Key Feature |
|---|---|---|
| Next.js | 16.x | Turbopack default, "use cache", proxy.ts, async params |
| TinaCMS | 3.x | Git-backed CMS, visual click-to-edit, GraphQL schema API, ESM-only |
| React | 19.x | Server Components, Actions, use(), useEffectEvent |
| Tailwind CSS | 4.x | CSS-first config (@import "tailwindcss"), no JS config needed |
| shadcn/ui | CLI v4 | Copy-paste components, npx shadcn create, tw-animate-css |
| Vercel | -- | Deploy target. @vercel/analytics, @vercel/speed-insights, Deploy Hooks |
| Tina Cloud | -- | Default CMS backend. Free tier (2 users), editorial workflow on Team Plus+ |
Quick Start
npx create-next-app@latest my-site --typescript --tailwind --app --src-dir
cd my-site
npx @tinacms/cli@latest init
Verify: tinacms dev then open http://localhost:3000/admin/index.html.
Local dev runs in local-only mode -- content reads/writes directly to the filesystem, no Tina Cloud connection needed. Production builds connect to Tina Cloud via NEXT_PUBLIC_TINA_CLIENT_ID and TINA_TOKEN env vars on Vercel.
Critical Knowledge
- Server-Client split is mandatory.
useTina()requires"use client". Every editable page needs a Server Component (data fetcher) + Client Component (visual editing wrapper). - Build order matters. Always
"build": "tinacms build && next build". Wrong order breaks withCannot find module '../tina/__generated__/client'. - Pin exact TinaCMS versions. No caret ranges. UI assets drift from CDN. Keep
tinacmsand@tinacms/*synced via package grouping (RenovateBot or Dependabot). tina/__generated__/should be gitignored. Onlytina-lock.jsonmust be committed. The__generated__/folder is rebuilt bytinacms build.- TinaCMS 3.x is ESM-only. Config files must use
importsyntax. Set"type": "module"inpackage.jsonor use.tsextensions. - Async params in Next.js 16. Every
page.tsx,layout.tsx,route.tsmustawait params-- sync access fully removed. proxy.tsreplacesmiddleware.ts. Lives at project root, exportsproxyfunction, runs Node.js runtime only. Codemod:npx @next/codemod@canary middleware-to-proxy .- Security: @tinacms/cli >= 2.1.8 required. CVE-2026-28792 (Critical, CVSS 9.6) -- drive-by attacks via CORS + path traversal in older versions.
- Dev command is
tinacms dev -c "next dev". Nevernext devalone -- the local GraphQL server won't run.
Version Floors
Look up current stable versions before scaffolding (npm view <pkg> version).
| Package | Minimum | Why |
|---|---|---|
next |
>= 16.0.10 | Security patches |
tinacms |
>= 3.3.x | Visual selector, ESM-only, current schema API |
@tinacms/cli |
>= 2.1.8 | CVE-2026-28792 fix |
react / react-dom |
>= 19.0.x | Server Components, Actions (19.2.x for useEffectEvent) |
tailwindcss |
>= 4.x | CSS-first config (v3.4.x also acceptable) |
| Node.js | >= 20.9.0 | Next.js 16 requirement |
Key Imports
| Import | From | Used For |
|---|---|---|
defineConfig |
tinacms |
Schema configuration in tina/config.ts |
useTina |
tinacms/dist/react |
Live editing in Client Components |
tinaField |
tinacms/dist/react |
Click-to-edit data attributes |
TinaMarkdown |
tinacms/dist/rich-text |
Rich text rendering |
client |
@/tina/__generated__/client |
GraphQL queries (auto-generated) |
Collections
Add based on project needs:
| Collection | Type | When Needed |
|---|---|---|
pages |
Folder + blocks | Always |
global |
Singleton | Always (site settings, SEO defaults) |
navigation |
Singleton | Always (can include footer links) |
posts |
Folder | If site has a blog |
authors |
Folder | If site has a blog |
footer |
Singleton | If footer warrants its own collection |
notFound |
Singleton | Optional |
Common Tasks
Create a new block
Add a template object to the blocks field's templates array in tina/config.ts. Every block needs ui.defaultItem. Optional: ui.previewSrc for visual selector thumbnails.
Add visual editing to a page
- Server Component fetches
{ data, query, variables }from Tina client - Client Component calls
useTina()with those props - Add
data-tina-field={tinaField(data.page, 'fieldName')}on DOM elements
Enable caching
Set cacheComponents: true in next.config.ts, then use "use cache" directive with cacheLife() presets: seconds, minutes, hours, days, weeks, max.
Deploy to Vercel
- Build command:
tinacms build && next build - Set Vercel env vars:
NEXT_PUBLIC_TINA_CLIENT_ID,TINA_TOKEN,NEXT_PUBLIC_TINA_BRANCH - Install
@vercel/analytics+@vercel/speed-insights, render<Analytics />and<SpeedInsights />in root layout - Set up a Deploy Hook for content change rebuilds
- Use Vercel Team Environment Variables to share keys across preview/production
Always use Tina Cloud unless the project has a specific reason to self-host. See references/deployment.md for self-hosted as a secondary option.
Claude Code Automations
Set up in .claude/settings.json early in Day 0:
{
"hooks": {
"PreToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "prompt",
"prompt": "If the file path contains 'tina/__generated__/' or ends with 'tina-lock.json', BLOCK this edit. These files are auto-generated by tinacms build and must not be manually edited."
}]
}],
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATH 2>/dev/null || true"
}]
}]
},
"permissions": {
"allow": [
"Bash(npx tinacms dev:*)",
"Bash(npx tinacms build:*)",
"Bash(pnpm dev:*)",
"Bash(pnpm build:*)",
"Bash(npx shadcn@latest add:*)"
]
}
}
MCP servers:
claude mcp add context7 -- npx -y @upstash/context7-mcp@latest-- live TinaCMS/Next.js/React/Tailwind docsclaude mcp add playwright -- npx -y @anthropic-ai/mcp-server-playwright@latest-- test visual editing in browser
Consider creating project-level skills for repeated tasks:
/new-block-- scaffold a block template + component + renderer mapping/tinacms-check-- audit schema for missingui.itemProps, brokentinaField, version drift
Agentic Workflow & Vibe Coding
- Iterative Building: Do not expect a perfect CMS integration on the first try. Draft the schema and visual editing wrapper, test the connection locally (
tinacms dev), isolate any specific data-fetching or rendering error, adjust exactly ONE field or query at a time, and refresh until the click-to-edit experience is seamless. - Vibe Coding: Commit your working Next.js pages and Tina schema configurations locally before attempting complex block template additions or deploying to Vercel. Ensure
tina-lock.jsonis included in these commits.
Reference Files
| File | When To Read |
|---|---|
references/schema-design.md |
Designing collections, blocks, fields, content hooks |
references/visual-editing.md |
Server/client split, draft mode, click-to-edit debugging |
references/seo-meta.md |
Metadata, JSON-LD, OG tags, sitemaps, RSS |
references/deployment.md |
Tina Cloud vs self-hosted, media providers, env vars |
references/setup-checklist.md |
Phased implementation checklist (MVP / Polish / Comprehensive) |
templates/tina-config-starter.ts |
Production tina/config.ts with 5 block templates |
templates/page-server-client.tsx |
Server/client page pattern with metadata and static params |
More from baphomet480/claude-skills
kitchen-sink-design-system
Kitchen Sink design system workflow for Next.js and React projects, with secondary support for Astro, SvelteKit, Nuxt, and static HTML. Use when asked for a Kitchen Sink page, Design System, UI Audit, Style Guide, or Component Inventory, or when a project needs a component inventory plus component creation and a sink page implementation. Covers CVA variant architecture, Tailwind v3/v4 token systems, shadcn/ui integration, and TinaCMS content modeling.
40deep-research
Conduct comprehensive, multi-round research that produces rich visual reports. Use when asked for "deep research", "comprehensive analysis", "compare frameworks", "evaluate options", "research the state of X", or any task requiring investigation across 10+ sources. NOT for quick lookups — this is a 5-15 minute deep dive that produces a briefing-quality artifact with screenshots, diagrams, tables, and cited findings.
37design-lookup
Search and retrieve CSS components, SVG icons, design patterns, and visual inspiration from the web. Use when the user asks to find, look up, or search for CSS snippets, SVG icons, UI components, loading spinners, animations, design inspiration, or any visual/frontend design resource. Triggers on requests like "find me a CSS button", "look up an SVG spinner", "search for a card component", "find a wave divider SVG", or "get design inspiration for a dashboard".
34cloudflare-pages
Deploy static sites to Cloudflare Pages with custom domains and CI/CD. Use when the user wants to deploy a site to Cloudflare Pages, add a custom domain to a Pages project, set up GitHub Actions CI/CD for Cloudflare Pages, roll back a deployment, or verify deployment status. Triggers on "deploy to Cloudflare", "Cloudflare Pages", "add custom domain", "pages deploy", or any Cloudflare Pages hosting workflow.
31local-ocr
Local OCR pipeline for AI agents featuring auto-rotation, deskew, and searchable PDF generation via ocrmypdf and Tesseract.
23hugo-sveltia-cms
Bootstrap new Hugo sites with Sveltia CMS and Basecoat UI, or convert existing sites (any SSG or CMS) to Hugo + Sveltia CMS. Use this skill whenever the user mentions Hugo, Sveltia CMS, Decap CMS migration, TinaCMS migration, static site CMS setup, headless CMS for Hugo, or wants to add a content management interface to a Hugo site. Also trigger when converting WordPress, Jekyll, Eleventy, TinaCMS, or other sites to Hugo, or when setting up Git-based content management. Covers the full workflow from scaffolding through Cloudflare Pages deployment with GitHub OAuth authentication.
14