Back to Blog
Tutorial10 min read2026-07-06

How to Deploy TinaCMS with a Git Backend

TinaCMS edits Markdown stored in your Git repo, giving you a visual editor without a database. Here's how the Git backend works, how to self-host Tina, and how to deploy editor plus site together.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

TinaCMS is a Git-backed headless CMS: instead of storing content in a database, it edits the Markdown and JSON files that already live in your repository, then commits the changes back to Git. For Jamstack sites this is appealing — your content is version-controlled, reviewable in pull requests, and there's no separate database to operate. But "Git-backed" hides some architecture you need to understand before deploying. This guide covers it.

How TinaCMS actually works

Tina has three moving parts:

  1. 1The editor UI — a React app, usually mounted at /admin on your site, that gives content editors a visual form-based interface.
  2. 2The content — Markdown/MDX/JSON files in your repo, described by a schema in tina/config.ts.
  3. 3The data layer / GraphQL API — Tina indexes your content into a GraphQL API. In production this is backed by Tina Cloud (the managed option) or a self-hosted data layer (Tina's self-hosted backend handler plus a database like MongoDB and a Git-token-authenticated backend).

The key decision is Tina Cloud vs self-hosted backend. Tina Cloud handles auth, the data layer, and Git commits for you. Self-hosting means you run the backend handler yourself and bring your own auth and database. Most teams start with Tina Cloud; self-hosting is for those who need full control.

Option A: Tina Cloud (managed backend)

This is the simplest production path. You sign up for Tina Cloud, connect your GitHub repo, and get a client ID and read-only token. Your site stays static; the editor talks to Tina Cloud, which commits to your repo.

Set these env vars in your build/runtime environment:

NEXT_PUBLIC_TINA_CLIENT_ID=your_client_id
TINA_TOKEN=your_read_only_token
TINA_SEARCH_TOKEN=optional_search_token

Build with Tina's wrapper so the admin and GraphQL types are generated:

{
  "scripts": {
    "dev": "tinacms dev -c \"next dev\"",
    "build": "tinacms build && next build"
  }
}

The tinacms build step generates the /admin/index.html editor and the typed GraphQL client. Deploy the resulting site as you normally would.

Option B: Self-hosted backend

If you self-host, you run Tina's backend handler (an API route) that handles auth and Git operations, backed by a database. The reference setup uses:

  • A backend API route (/api/tina/[...routes]) using @tinacms/datalayer
  • A database adapter (MongoDB is the documented default) for the content index
  • An auth provider (Tina's AuthJsBackendAuthProvider or your own)
  • A GitHub personal access token for commits

The backend needs a database. TinaCMS documents MongoDB for the self-hosted data layer. On PandaStack you can provision a managed MongoDB and inject its connection string as an env var, so the self-hosted backend has a durable index without you operating a database. Set:

GITHUB_PERSONAL_ACCESS_TOKEN=...
GITHUB_OWNER=your-org
GITHUB_REPO=your-repo
GITHUB_BRANCH=main
MONGODB_URI=...   # from your managed MongoDB
NEXTAUTH_SECRET=...

Because the self-hosted backend is a Node server (API routes), this variant is a container deployment, not a pure static site. Your Next.js app with the Tina backend route deploys as a container; on PandaStack that's a Dockerfile or buildpack build via rootless BuildKit, with the managed MongoDB auto-wired.

Deploying the editor and site together

The nice property of Tina is that the editor (/admin) and your site ship together — the editor is just static assets generated at build time. So:

  • Static site + Tina Cloud: deploy as a static site. The /admin route is static; the data layer is Tina Cloud. On PandaStack this is a free static deployment with automatic SSL.
  • Self-hosted backend: deploy as a container (the backend route needs a server runtime), with a managed MongoDB attached.

For the static-site path, configure:

  • Build command: tinacms build && next build (or your framework's equivalent — Tina supports Hugo, Astro, etc., via its content layer)
  • Output: your framework's build output (e.g. .next for SSR, out for static export)
  • Env vars: NEXT_PUBLIC_TINA_CLIENT_ID at build time, TINA_TOKEN available to the build

Editorial workflow and branching

Tina supports an editorial workflow where edits go to a branch and become a pull request rather than committing straight to main. This pairs well with preview deployments: each branch/PR can get its own preview build so editors see changes before merge. If your host supports per-branch deploys, wire that up — it turns content editing into the same reviewable flow as code.

Common pitfalls

  • Forgetting tinacms build. Running only your framework's build skips generating /admin and the typed client. The editor 404s.
  • Token scope. The GitHub token (self-hosted) or Tina Cloud token needs the right repo permissions to commit. Read-only tokens can read but not save edits.
  • CORS / domain mismatch (Tina Cloud). Add your deployed domain to the allowed sites in the Tina Cloud project settings, or auth will fail.
  • Large media. Tina can store media in the repo or in an external store (e.g. Tina's media or a cloud bucket). Committing large binaries to Git bloats the repo fast — use an external media store for image-heavy sites.

Which option to choose

NeedChoose
Simple, fast, no DB to runTina Cloud + static site
Full data residency / no third-partySelf-hosted backend + managed MongoDB (container)
Editorial review via PRsEither, with branch-based workflow

References

  • TinaCMS docs: https://tina.io/docs/
  • Self-hosted TinaCMS guide: https://tina.io/docs/self-hosted/overview/
  • Tina GraphQL / data layer: https://tina.io/docs/graphql/overview/
  • Tina editorial workflow: https://tina.io/docs/drafts/editorial-workflow/
  • MongoDB documentation: https://www.mongodb.com/docs/

---

Going self-hosted with TinaCMS? PandaStack gives you a container deployment plus a managed MongoDB with backups, auto-wired via env vars — and a free static tier if you stay on Tina Cloud. Start at https://dashboard.pandastack.io.

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also