Loving Tina? us on GitHub0.0k

Docs

Learn

v.Latest
Documentation
Separate Content Repo
Table of Contents

Introduction

Tina supports sourcing content from a separate Git repo. With this approach you can continue to define your Tina config in your "website repo", but documents will be saved elsewhere.

Why?

You might want to do this for a variety of reasons, such as:

  • To decouple your website code from your content files so your commit history isn't a mix of content updates and code updates
  • To avoid having to give TinaCloud write access to your website's code (only give access to your content repo)

Throughout this guide we'll be referring to a "website repo" and a "content repo". The "website repo" is where your actual website is running, while the "content repo" is where you'll be storing your markdown content

Requirements

  • You must have both the "content repo" and the "website repo" checked out onto your local machine.
  • You must provide the location of your content repo in your Tina config (more about that below).
  • When making changes, you'll need to ensure you've pushed both repos to GitHub, with the "content repo" changes first
  • When making changes you will need to sync the generated files in tina/ (such as tina-lock.json, __generated__ files etc) between your website repo and content repo

Create the website repository

We have deployed a basic starting "website repo", which you can clone to get started.

git clone git@github.com:tinacms/separate-website-repo.git

The "website repo" contains the NextJS site, and the tina config.

Create the content repository

To set up the "content repo", we'll start with a simple .mdx file:

mkdir -p ../demo-content-repo/content/pages && touch ../demo-content-repo/content/pages/home.mdx && echo "Hello" >> ../demo-content-repo/content/pages/home.mdx

This command creats a folder (demo-content-repo) and added a single MDX file to it in the content/pages directory, we'll be using that directory for the page collection defined in the Tina config.

Local Development

In the "website repo", install the project's dependencies

yarn install

Run the project locally:

yarn dev

Visit the page in edit mode

Open http://localhost:3000/admin/index.html.

From here you can add more fields to you content models in tina/config.js. Visit the docs to learn more about content modeling.

Deploying your content repo

Next we'll want to create a TinaCloud project from our "content repo"

  1. Initialize Git in your content repo and push it to GitHub.
  2. Once that's done, create a token for the main branch, or use * to allow all branches.

Switch back to your "website repo" and set up an .env file to use when connecting to TinaCloud:

cp .env.example .env

When you run tinacms build, it will use those credentials to connect to TinaCloud rather than the local server:

yarn build

Managing Schema Changes Across Repos

When you modify your Tina schema ( tina/config.(ts/js) )

  1. Run tinacms build to regenerate files - Tina will regenerate files such like your tina-lock.json
  2. Commit and push these changes to **both **your website repo and content repo to ensure compatibility across builds

Path Configuration Considerations

When defining collection paths inside your tina/config.(ts/js), avoid setting `path: '' . As Tina expects a folder-relative path. Using an empty string '' can result in errors when creating new documents because Tina prepends a / when saving, which can lead to invalid GitHub paths and creation errors.

Static Site Generator Compatibility

If you are using a static site generate (SSG) other than Next.js, such like Astro. Ensure your content pipeline ignores the tina/ directory inside your content repo. Tina's config files are not content files and this may cause parsing errors.

Here's an example of how to exclude the `tina/` directory:

export default defineCollection({
schema: mySchema,
exclude: ['tina/**/*'],
});

Triggering Website Builds from the Content Repo (Optional)

When using a separate content repo, you may want content updates (e.g. from TinaCMS UI) to automatically trigger a build of your website. TinaCloud supports this out of the box using webhooks.

TinaCloud can be configured to send a POST request to a webhook endpoint whenever content changes are committed. This is the recommended way to trigger a rebuild of your website.

๐Ÿ‘‰ Check out the webhook functionality for more details

Triggering Builds with GitHub Actions

As an alternative to using webhooks, you can trigger website builds with GitHub Actions.
This is useful if your platform doesnโ€™t support build webhooks, or if you want more control over the build process.

Example Workflow

Create a workflow file in your content repo (e.g. .github/workflows/trigger-website-build.yml):

name: Trigger Website Build
on:
workflow_dispatch:
push:
branches:
- '**'
jobs:
trigger-deploy:
runs-on: ubuntu-latest
if: github.repository_owner == 'your-org'
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.MY_APP_ID }}
private-key: ${{ secrets.MY_APP_PRIVATE_KEY }}
owner: your-org
repositories: your-website-repo
- name: Trigger website deploy
run: |
gh workflow run build-and-deploy.yml \
--repo your-org/your-website-repo \
--ref main \
--field run_id="$GITHUB_RUN_ID" \
--field branch_name="${GITHUB_REF#refs/heads/}"
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
Prerequisites

This setup requires:

  • A GitHub App with access to both repos
  • Token and app secrets saved in GitHub repo settings
Last Edited: July 9, 2025