TinaCMS supports using external media providers, however a light backend media handler needs to be setup/hosted by the user. TinaCMS offers some helpers to make this easy, for cloudinary,s3, & dos ("Digital Ocean Spaces").
You'll also need to define your own authorization function, to check if users are allowed access to the handler.
Depending on your site's framework & hosting provider, there are multiple ways to host the media handler.
In the following examples, replace <YOUR_MEDIA_STORE_NAME> with cloudinary,s3, or dos.
Set up a new API route in the pages directory of your Next.js app at pages/api/<YOUR_MEDIA_STORE_NAME>/[...media].ts.
Then add a new catch-all API route for media by calling createMediaHandler method of your media store library.
Import isAuthorized from "@tinacms/auth".
The authorized key will make it so only authorized users within TinaCloud can upload and make media edits.
Vercel supports creating Serverless functions by creating a /api directory at the project root. To set this up, follow the above NextJS-specific instructions, but use /api/<YOUR_MEDIA_STORE_NAME>/[...media].ts instead of /pages/api/<YOUR_MEDIA_STORE_NAME>/[...media].ts
Note: You may notice that the package names may contain "next" (e.g: next-tinacms-cloudinary). You can still use these packages for other frameworks.
If your site is hosted on Netlify, you can use "Netlify Functions" to host your media handler.
First, you must set up redirects so that all requests to /api/* can be redirected to Netlify Functions. You can set up redirects at netlify.toml. We are also going to build our functions with esbuild so we will set that in the netlify.toml as well.
Add the following to the netlify.toml file in the root of your project.
Next, you must set up api routes for the media handler.
Install the following dependencies.
Make a new file called netlify/functions/api/api.js and add the following code.
If your site is hosted on AWS, you can use AWS Lambda to host your media handler. The following example
uses the S3 media handler, but you can use any media handler.
npm install express @vendia/serverless-express @tinacms/auth body-parser
To connect TinaCMS endpoints to AWS services, you'll need to create a Lambda Function in Node 14.x. Here's the code you'll need:
Be sure to configure the necessary environment variables:
With the Lambda Function in place, you can proceed to create an API Gateway:
Click on Create API
Select REST API
Once the API is created, create a resource under the root path named /api by going to Resources and selecting Create Resource
Next, create a nested child path that takes all /api child paths by creating a resource that uses the {proxy+} special syntax. Make sure to tick the Configure as proxy resource.
When setting up the ANY method, pass the Lambda Function that handles the TinaCMS media manager logic.
Click on save and allow API Gateway to add permission to the Lambda Function
Deploy your API by clicking on the Action dropdown and selecting Deploy API
Select [New Stage] for the Deployment Stage and type a Stage name
Once the API is deployed, you can see the Invoke URL in the Stages menu by clicking on the stage you've created.
Configure Binary Media Types by going to the Settings Menu and adding the /* wildcard
To complete the connection, create a new Origin for CloudFront using the Invocation URL of the API Gateway that was just created. Set the Origin Path to the name of the stage where the API was deployed.
Create a new Behaviour for CloudFront that will intercept requests with the /api/s3/media* path and use the API Gateway origin that was just created. Make sure to allow the following HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, and DELETE.
Under the Cache key and origin requests section, select the Cache policy and origin request policy option. For the Cache policy, select CachingDisabled. For the Origin request policy, select AllViewerExceptHostHeader.
Repeat the above process to create another behaviour that intercepts requests with the /api/s3/media/* path.
Now, you can replace the default repo-based media with the external media store. You can register a media store via the loadCustomStore prop.
The loadCustomStore prop can be configured within tina/config file.
Make sure you commit your changes to the config and tina-lock.json file at the same time as you push to production on TinaCloud as otherwise your assets will still be prefixed with https://assets.tina.io as if you were still using repo based media
Now you can manage external media store inside TinaCMS. To learn more about each media store in detail, please refer to the next sections.