Tina blog setup
Markdown posts live in content/post/. Subfolders appear as sections on /posts. The visual editor is at /admin after a production build, or while running dev with Tina.
Websites
| What | URL |
| Tina Cloud (project, Client ID, API tokens) | https://app.tina.io |
| Tina documentation | https://tina.io/docs |
Steps
- Sign in at app.tina.io and create a project.
- Connect the same GitHub repository you deploy from (Tina indexes Markdown on your branch).
- Copy the Client ID from the project dashboard.
- Open Tokens and create a token for CLI / CI (used by
tinacms buildandnpm run build).
Local environment
Create .env.local at the repo root (never commit):
NEXT_PUBLIC_TINA_CLIENT_ID=your-client-id-uuid
TINA_TOKEN=your_tina_token
# Optional default branch:
# NEXT_PUBLIC_TINA_BRANCH=main| Variable | Exposed to browser? | Role |
NEXT_PUBLIC_TINA_CLIENT_ID | Yes | Binds Admin and builds to your Cloud project |
TINA_TOKEN | No | Required for tinacms build / production builds |
NEXT_PUBLIC_TINA_BRANCH | Yes | Optional; defaults to git / Vercel branch if unset |
Alternative (client id only): copy tina/tina.local.example.json to tina/tina.local.json with { "clientId": "your-uuid" }. The script scripts/load-tina-env.cjs merges .env, .env.local, and that file. Keep TINA_TOKEN in .env.local or CI secrets only.
Commands
npm run dev: Tina GraphQL (default port 4001) and Next.js; removes stalepublic/adminso Admin matches the local schema.npm run build: runstinacms buildthennext build. RequiresNEXT_PUBLIC_TINA_CLIENT_IDandTINA_TOKEN.
Deploy and CI
| Platform | Where to add variables |
| Vercel | Project Settings > Environment Variables (step-by-step: Vercel environment variables) |
| GitHub Actions | Repo Settings > Secrets and variables > Actions |
Use the same names as in .env.local. Optional: repository variable NEXT_PUBLIC_TINA_BRANCH.
Repo files to know
tina/tina-lock.json: commit after schema changes.tina/__generated__/: regenerated by builds; local dev targetshttp://localhost:4001/graphql.- Unicode paths (e.g. non-ASCII folder names) are supported; see
src/lib/blog-path.js.
Troubleshooting
| Issue | What to do |
Datalayer server is busy on port 9000 | Stop other tinacms dev processes, or set TINA_DATALAYER_PORT (e.g. 9001) in .env.local if your workflow supports it. |
| Admin / client undefined | Set NEXT_PUBLIC_TINA_CLIENT_ID, restart dev. |
| Build fails: missing token | Add TINA_TOKEN everywhere you run npm run build. |