Sanity and Nextjs for CI / CD
Sanity and Next.js for Seamless CI/CD: A Guide
In development, optimizing workflows for efficiency is crucial, not only for internal processes but also for improving the end-user experience. CI/CD (Continuous Integration and Continuous Delivery) plays a pivotal role in achieving these goals by automating testing, accelerating deployment, and allowing teams to deliver updates and features more rapidly. Combining Sanity as a flexible headless CMS with Next.js as a powerful web framework creates a dynamic setup, giving developers precise control and speeding up project iterations. Here’s how to integrate Sanity Nextjs CI/CD to streamline your process and deliver a smoother, faster experience for your users.
Why Choose Sanity and Next.js for Your Projects?
A Perfect Pair: Sanity and Next.js
Sanity and Next.js work perfectly together to create an efficient, high-performing workflow for content-driven applications. Sanity provides a flexible, headless CMS where content is easily managed, while Next.js serves as a powerful framework for fast and optimized web applications.
Using Incremental Static Regeneration (ISR) in Next.js, you can set up static site generation that updates specific pages whenever new content is created or modified in Sanity, reducing the need for full rebuilds. The synergy allows you to quickly serve updated content with minimal impact on performance, creating a smoother experience for your users.
Sanity: A Headless CMS Built for Flexibility
Sanity is a top-tier headless CMS content management system, offering developers and editors both full control and flexibility. The latest Sanity Studio v3 introduces a rich editorial experience, where creators can simply click on UI elements to open and edit corresponding fields, making content updates intuitive and efficient.
Developers also have full customization options, from default structures to custom tabs and logic, allowing the Studio to be precisely tailored to project needs. High-level of flexibility is a standout advantage, making Sanity a preferred choice for building scalable and adaptable content management solutions.
Next.js: Speed and Control for Modern Web Development
Next.js has become one of the most popular frameworks for building fast, high-quality web applications. Its flexibility includes granular control over page load speeds and rendering options, along with powerful tools like middlewares and API routes.
With ISR, Next.js allows you to generate static pages that update dynamically, combining the performance benefits of static sites with the flexibility of real-time data updates. For developers, Next.js represents a balance between speed, control, and ease of use, making it ideal for projects where performance and scalability are priorities.
Learn how to optimize performance in Next.js from our CEO and CTO:
CI/CD with Sanity and Next.js: Speed Up Development and Delivery
CI/CD – Continuous integration and Continuous Deployment/Delivery is essential for streamlining the testing and delivery process, allowing for faster iterations and reducing manual workload. Below, we’ll walk through setting up CI/CD for a Next.js project integrated with Sanity, showcasing a solution to accelerate development and ensure smooth, efficient deployment.
Wondering if Sanity and Next.js are a good pick for your project?
Setting Up Sanity
Sanity Studio is the central admin panel for managing all your content and editorial workflows. And we will focus on it during this process. It’s fully customizable, allowing you to define and style the interface from code to fit your project’s specific needs. You can choose from a variety of configurations, from default structures to adding custom tabs and logic for a tailored experience.
For an in-depth guide on customization options, visit the Sanity Structure Builder documentation.
With Sanity Studio, you have two hosting options:
- Host on Sanity Cloud: This option is ideal if you want to manage content across multiple applications or don’t need Studio hosted directly on your domain. In this setup, Sanity Studio is hosted separately, and you’ll need a dedicated repository for it.
- Self-Host within Your Application: If your content is specific to one application, you can embed Sanity Studio directly within your Next js app. This means you can host Studio on a custom route like
/sanity-studio
, making it a seamless part of your application’s codebase.
Hosting on Sanity Cloud – Step by Step
1. Create a New Sanity Project:
- Create an account if you don’t have one in Sanity.
- Create a new project:
- For simplicity we can select “Quickstart with schema” so we will have some initial schemas at start.
- Select Marketing site with page builder and click Deploy Studio
Thats it! Your studio is deployed and ready to work. Now let’s create a repository for this code and setup the CI/CD to keep this studio up to date!
2. Connecting Sanity to GitHub
- Initialize a new repository on GitHub
- Sign in to Sanity using CLI just typing “`
sanity login
“` in your console and log to your account - Initialize the sanity project with:
npm create sanity@latest -- --quickstart {projectId}
and just follow up with the configuration. - Create an env file and put your details there:
```
SANITY_STUDIO_PROJECT_ID=your_project_id_here
SANITY_STUDIO_DATASET=production
```
- Update your
sanity.cli
andsanity.config.ts
files to use env variables instead of hardcoded values
Your sanity.cli
should look like this:
import {defineCliConfig} from 'sanity/cli'
export default defineCliConfig({
api: {
projectId: process.env.SANITY_STUDIO_PROJECT_ID,
dataset: process.env.SANITY_STUDIO_DATASET,
},
})
And here’s how sanity.config.ts
should look like:
```
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {visionTool} from '@sanity/vision'
import {schemaTypes} from './schemaTypes'
export default defineConfig({
name: 'default',
title: 'Test project',
projectId: process.env.SANITY_STUDIO_PROJECT_ID || '',
dataset: process.env.SANITY_STUDIO_DATASET || '',
plugins: [structureTool(), visionTool()],
schema: {
types: schemaTypes,
},
})
Now go to the Sanity management and select your project and go to the API tab. Click on Add New Token button and select Deploy Studio option.
Go to GitHub repository and add a secret with this token: Settings > Secrets And variables > Actions > New secret. Remember to add projectID
and dataset variables at this point.
Add workflow for GitHub actions in your code. Create a .github/workflows/sanity.yml
file in root of your project and put this content inside:
name: Deploy Sanity action
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
cache: npm
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Deploy Sanity Studio
env:
SANITY_AUTH_TOKEN: ${{ secrets.SANITY_AUTH_TOKEN }}
SANITY_STUDIO_PROJECT_ID: ${{ secrets.SANITY_STUDIO_PROJECT_ID }}
SANITY_STUDIO_DATASET: ${{ secrets.SANITY_STUDIO_DATASET }}
run: |
npm install -g @sanity/cli
sanity login --token $SANITY_AUTH_TOKEN
sanity deploy --non-interactive
It’s a very simple workflow that will just install all required dependencies and run 2 commands sanity login
using the token from secrets and sanity deploy
to deploy the studio. This workflow will be triggered on any pushes to the main branches.
It will use the sanity.ci.ts
file to get the project configuration, which is why we need to add these 2 extra secrets (PROJECT_ID & DATASET). Now you can update your schemas, push the code, and see if it works correctly.
You can find a code for this solution here: https://github.com/Pagepro/sanity-ci
Setting Up Next.js
If you decide to go with self-hosted studio inside of your Nextjs app we need to start with creating a Nextjs project.
Creating a New Next.js Project
You can use any existing project if you want – if you will use your existing project you can skip this step
Start by creating a new project by typing this in your terminal:
`npx create-next-app@latest`
Follow the setup and you should be ready to go. Next, create a new repository in GitHub and add origin to your new project.
`git remote add origin [email protected]:yourpath/sanity-next-ci.git`
`git branch -M main`
`git push -u origin main`
Now we have a project that we can use in our Vercel account. Let’s start from that step.
Configuring CD with Vercel
Introduction to Vercel
Vercel is a cloud platform that enables developers to deploy, scale, and manage web applications with ease. It specializes in hosting Jamstack applications, such as those built with Next.js, and provides automatic deployments and optimization for performance. Vercel integrates seamlessly with GitHub automatically deploying code changes and offering both preview and production environments.
Connecting GitHub Repository to Vercel
To setup CI/CD for our Nextjs app on Vercel we just need to connect our repository to Vercel and follow a few quick steps:
- Create an account and a project in Vercel. Connect Vercel & GitHub so we can select one of our repositories and then find your repository and click the Import button:
- Select your repository with the NextJS app. In the configuration select Next.js as a framework so it will prefill the build and output settings for us.
- If you want to customize the build process open the build and output settings and you can change the command or root directory of your project.
If everything is ok just click the Deploy button. You can watch the progress now and get familiar with the logs, or we can jump to the next section in the meantime. On a successful deploy, you should be able to see the project’s URL and check the deployment.
Automatic Deployments
Vercel will now automatically build & deploy your main branch every time you push any changes to it. You can add your own domain or use the Vercel ones.
Add Sanity Studio to our Nextjs project
Setup Sanity Within Your Project
There are a few ways to embed the studio, but we will use the simplest one.
Start with Installing next-sanity
package npm i next-sanity sanity
. Then create a env
file in the root of the project and add these variables:
NEXT_PUBLIC_SANITY_PROJECT_ID=your_id_here
NEXT_PUBLIC_SANITY_DATASET=production
Create a new file in your app
directory /admin/[[...index]]/page.tsx
and add this code:
"use client";
import { defineConfig } from "sanity";
import { structureTool } from "sanity/structure";
import { NextStudio } from "next-sanity/studio";
import { schemaTypes } from "../../schemaTypes";
const sanityConfig = defineConfig({
title: "Sanity CI/CD test",
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
apiVersion: "2024-04-23",
basePath: "/admin",
plugins: [structureTool()],
schema: {
types: schemaTypes,
},
});
export default function AdminPage() {
return <NextStudio config={sanityConfig} />;
}
For simplicity, copy the schemaTypes from the previous project and paste it into the src/app
directory. The project structure should look like this:
Now run the project in development mode npm run dev
. If you followed my instructions you should see this screen on the http://localhost:3000/admin URL
To get rid of it, we need to go to the sanity dashboard API > CORS origins. Click on Add Cors origin and make sure you select “allow credentials”, as it’s required for the studio. After that, you should be able to see your studio now.
You will also have to follow the Cors instructions with the Vercel domain. But now, let’s adjust our Vercel configuration to handle the studio.
So, we have a Sanity studio set up in the local environment. Let’s update our Vercel so we have a CI/CD process ready. Go to Vercel, select your project, click on the Settings tab, and select Environment Variables from the left:
Create a new env variable with the same names as in our .env file : NEXT_PUBLIC_SANITY_PROJECT_ID & NEXT_PUBLIC_SANITY_DATASET
.
hINT
You can copy content of .env file and just paste it here in first Key position, and it will automatically create all of your env variables for you.
Now it should look like this:
Click the Save button and they should appear at the bottom.
Now we are ready to go. If you didn’t push your changes with Studio, it’s a good time to test it! If you already did, update anything in our code (add some text on the homepage) and push the changes. We should see that we’ve triggered the build process.
It should throw an error as we have a page.ts file
in our schemaTypes directory:
It’s a sample of the error log. We just need to rename this file to anything else like pageType.tx
or move it to a different directory as page.ts
name is dedicated to routes in Nextjs.
Advanced CI/CD Configurations
Custom Logic in the CI Runtime
In Vercel you can change the build command to your own script that will first call some linting stage, then trigger tests, and finally build the application.
In GitHub actions (it’s part of the dlow) add the steps that you want and they will be executed one by one.
Handling Environment Variables
Vercel allows to set the variables for all or specific branches. When you create a new variable you can select the Production, Development, or Preview branch. In Preview you can even specify the exact branch name you want to use, it’s very flexible.
For GitHub actions, it’s a little bit more complicated, as you have a few paths to follow. You can conditionally access secrets based on the branch using if conditions.
```
- name: Deploy the app
if: github.ref == 'refs/heads/main' # Only use secrets on the 'main' branch
run: deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
```
You can restrict workflows to run only on specific branches.
on:
push:
branches:
- main # Only trigger the workflow on the 'main' branch
Use environments to manage secrets that are tied to specific workflows and set these environments in your pipeline
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # Use production environment secrets
Branch Deployments
To set up different branches in GitHub actions like production/staging/development you can create separate workflows (remember to use correct env
variables for specific environments) or add all of them here:
on:
push:
branches:
- main
- staging
- development
For Vercel all branches are automatically deployed as Preview Deployments when pushed to GitHub, making it easy to test your changes on staging/preview deployment. Preview deployment is using your env
variables set to preview branches (or main ones if you didn’t set them specifically).
Monitoring and Alerts
If your CI/CD fails either on the Vercel or GitHub actions, you will see it in the dashboard. If you have your email notifications on, you should also receive an email about it. In the logs, you can see exactly which steps were successful and which ones failed. Here’s an example of GitHub actions log:
Example Vercel log:
Best Practices and Tips
Optimizing Build Times
By default, actions are run in fresh virtual environments, so in a way, they start from scratch. However, you can use caching to save time. For example, when building a project or running tests, certain files (like dependencies) don’t need to be downloaded every time. You can cache these files between workflow runs to speed up future runs.
Security Considerations
Like in our example, you should always hide your variables from exposure. GitHub provides encrypted secrets to store sensitive data, such as API tokens. These secrets can be accessed within workflows but remain hidden in logs and are protected. In our example, we are using secrets for the project ID, dataset, and auth token instead of hardcoding them in the workflow file. The same thing for Vercel – they are not visible in the logs and are not exposed to users.
Conclusion
As you see setting up CI/CD for Sanity or Nextjs app is very easy. You only need an hour to save at least 20 hours during development and performing everything manually.
Once you get familiar with the basics, you can build your own custom GitHub actions that will match your criteria for CI/CD. Almost everything that you can do manually can be automated – you just need to generate a token to get access or add some extra code to handle the scenario.
I highly recommend using AI as a personal helper. You ask ChatGPT or Cursor to write a workflow for you. Describe what you need and it should generate the code for you, and with the help of documentation you can make it work and it’s even easier than writing it from scratch.
Ready to start using Sanity and Next.js?