Loving Tina? us on GitHub0.0k
v.Latest
Documentation

Repo-based Media

Loading last updated info...
On This Page

TinaCMS has a built-in Repository (git) based media storage option. Alternatively, you can connect your CMS to an external media storage provider.

Repo-based media keeps your assets alongside your content, meaning you can track changes and roll back versions for both code and media.

This has other benefits such as reducing dependencies on external APIs and keeping local development and preview environments in sync.

Not seeing your media? For newly created projects, an initial media sync is triggered automatically and may still be in progress. If your media still isn't appearing, you can manually trigger a sync from the Media tab in your TinaCloud project dashboard.

Configuration

To configure repo-based media in your project, add the following to your schema definition in tina/config.{ts,js}:

//tina/config.{ts,js}
export default defineConfig({
// ...
media: {
tina: {
publicFolder: 'public',
mediaRoot: 'uploads',
static: false, //default is false
},
},
});

Asset Storage Path

Set publicFolder to the path to your site's "public" folder. This path is relative to your project's root.

For any Next.js site (such as our tina-cloud-starter), this value should be "public".

Media Storage Path

The path to your media folder, relative to the publicFolder value.

Set this to "", if you want your media to be uploaded to the root of your publicFolder.

Anything in this directory will be synced with TinaCloud's media server, and the images will be publicly accessible.

Media Permissions

The static property determines whether media files can be uploaded, edited, or deleted directly through the editor.

  • static: true: Editors cannot upload/delete media (static assets)
  • static: false (default): Editors can upload/delete media (dynamic assets).

Supported Media Types

The following file types are supported by default:

Format

MIME Type

Examples

Adobe InDesign

application/x-indesign

.indd

Apple HTTP Live Streaming

application/vnd.apple.mpegurl

.m3u8

Binary File

application/octet-stream

.bin

Filmbox

model/fbx

.fbx

GL Transmission Format (JSON)

model/gltf+json

.gltf

Images

image/*

.jpg, .png, .gif, etc.

JSON

application/json

.json

JSON-LD

application/ld+json

.jsonld

Material Exchange Format

application/mxf

.mxf

Microsoft Excel (Legacy)

application/vnd.ms-excel

.xls

Microsoft Excel (OpenXML)

application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

.xlsx

Microsoft Word (Legacy)

application/msword

.doc

Microsoft Word (OpenXML)

application/vnd.openxmlformats-officedocument.wordprocessingml.document

.docx

MPEG-DASH

application/dash+xml

.mpd

PDF

application/pdf

.pdf

Polygon File Format

model/ply

.ply

PostScript

application/postscript

.ps, .eps, etc.

Text Files

text/*

.txt, .md, etc.

U3D Mesh

model/u3d+mesh

.u3d

USDZ Zip

model/vnd.usdz+zip

.usdz

Videos

video/*

.mp4, .avi, .mkv, etc.

If you would like to specify your own allowed file types, add the following to the media property:

//tina/config.{ts,js}
export default defineConfig({
// ...
media: {
tina: {
//..
},
accept: ['image/jpeg', 'video/mp4'],
},
});

NextJS Images

If you are using Next.js images, you will need to add something like the following to your next.config.js file to allow access to external images.

module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.tina.io',
port: '',
},
],
},
};

Learn more about Next.js remote patterns.

Maximum file size

When uploading files to TinaCloud, the maximum allowed file size is 100 MiB.

How does this work with Editorial Workflow?

By default, repo-based media is scoped to a single media branch (your repository's default branch), and every editing branch reads and writes its assets there.

When your project has Editorial Workflow enabled, media becomes branch-aware and goes through the same review process as your content:

  • Each branch has its own view of your media, so uploads and deletes on one branch do not affect other branches until they are merged.
  • When you upload or delete media while editing a protected branch, TinaCMS does not write straight to it. Instead it prompts you to create a working branch, saves the asset to that branch, and opens a pull request, just like saving content. You are switched onto the new branch and can keep working, and the change reaches the protected branch only once the pull request is merged.
  • You can choose Save to protected branch in the prompt to bypass the workflow and write directly.

See Media in the Editorial Workflow for the full flow.

Caveats

  • The media workflow only triggers when the branch you are currently editing is itself protected. On a non-protected working branch, uploads and deletes are saved directly to that branch.
  • Each media upload or delete on a protected branch creates its own working branch and pull request. All subsequent media operations on that branch will be appended to the created pull request"
  • Images cannot be altered in place. Once uploaded, subsequent changes to an asset are not reflected, so upload a new file instead.

If you are configuring Tina on a non-default branch (and the Tina config has not yet been merged to your default branch), the automatic media sync on project creation may not be able to locate your media configuration. In this case, the Media tab in your TinaCloud project dashboard will show that media has not yet been synced. Once your Tina config has been merged to the default branch, you can trigger a sync manually from that tab.

Renaming Media Files

Repo-based media does not support renaming files through the Media Manager — the UI has no rename action today. To rename a file, you need to delete-and-re-upload via the Media Library, or make the change directly in GitHub.

Prevention: Avoid filenames with spaces, accents, or special characters. Lowercase ASCII with hyphens (e.g. my-image.jpg) is the safest bet — filenames with special characters have been seen to break downstream builds (e.g. Astro). First-class filename sanitisation on upload is tracked in tinacms#6359.

Workaround 1 — Delete and re-upload via the Media Library:

  1. Delete the file from the Media Library in TinaCMS
  2. Re-upload the file with the new filename

Workaround 2 — Rename directly in GitHub:

  1. Navigate to your repository on GitHub and locate the media file in your media directory (e.g. public/uploads/)
  2. Delete the old file directly in GitHub
  3. Wait for the deletion to sync back to TinaCloud
  4. Add the file with the new name directly in GitHub
  5. Wait for the new file to sync back to TinaCloud
If the tracked branch has branch protection rules enabled, attempting to upload via the Media Library will save the file to the media storage (S3) but the change will not be committed to the protected branch. In that setup, use Workaround 2.
First-class rename support in the Media Library is tracked in tinacms#6722.