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.
You might want to do this for a variety of reasons, such as:
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
First, create a new Tina project. To help you get started we've created a basic starting "website repo", which you can clone to follow along.
git clone git@github.com:tinacms/separate-website-repo.git
The "website repo" contains a NextJS site, and the tina config with the local config path already configured.
Next we'll setup the "content repo". Lets create a simple simple .mdx file to start with:
tree .# .# βββ separate-website-repo## 2 directories, 0 filesmkdir -p demo-content-repo/content/pagescd demo-content-repotouch ./content/pages/home.mdxecho "Hello" >> ./content/pages/home.mdxcd ..tree .# .# βββ demo-content-repo# βΒ Β βββ content# βΒ Β βββ pages# βΒ Β βββ home.mdx# βββ separate-website-repo## 5 directories, 1 file
This command creates a folder (demo-content-repo) and adds 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.
In the "website repo", install the project's dependencies
yarn install
Run the project locally:
yarn dev
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.
Next we'll want to create a TinaCloud project for our "website repo"
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
Now that the βwebsite repoβ has been created in TinaCloud, grab the client ID for the project and create a new tina/meta.json file in the content repo.
cd demo-content-repomkdir tina/touch tina/meta.json
Then add the following contents into tina/meta.json
{"upstreamBranch": "main","upstreamClientId": "{{ client ID }}"}
Previous versions of TinaCMS required you to maintain an up-to-date `/tina` folder in both repositories. This has now been simplified to a single
tina/meta.jsonfile. If you're migrating from the way it used to be, ensure to update the repo in TinaCloud from the βcontent repoβ to the βwebsite repoβ.
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.
If you are using a static site generator (SSG) other than Next.js, such as 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/**/*'],});
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
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.
Create a workflow file in your content repo (e.g. .github/workflows/trigger-website-build.yml):
name: Trigger Website Buildon:workflow_dispatch:push:branches:- '**'jobs:trigger-deploy:runs-on: ubuntu-latestif: github.repository_owner == 'your-org'steps:- name: Generate a tokenid: generate-tokenuses: actions/create-github-app-token@v2with:app-id: ${{ vars.MY_APP_ID }}private-key: ${{ secrets.MY_APP_PRIVATE_KEY }}owner: your-orgrepositories: your-website-repo- name: Trigger website deployrun: |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 }}
This setup requires: