Sanity and Nextjs for CI / CD

PageproPagepro
13 min read

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.

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.

Sanity Studio in Sanity Nextjs CI CD

With Sanity Studio, you have two hosting options:

  1. 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.

  2. 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:

New project in Sanity Nextjs CI CD

  • 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

Quickstart in Sanity Nextjs CI CD

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 and sanity.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 git@github.com: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:

schemaTypes

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

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.

CORS origins

CORS origins cont'd

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:

Project Settings

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:

View

Click the Save button and they should appear at the bottom.

Variables

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.

Deployments

It should throw an error as we have a page.ts file in our schemaTypes directory:

Error

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.

Build and development in Sanity Nextjs CI/CD

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.

Environment Variables in Sanity Nextjs CI/CD

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

Configure production in Sanity Nextjs CI/CD

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:

GitHub actions log in Sanity Nextjs CI/CD

Example Vercel log:

Vercel log in Sanity Nextjs CI/CD

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.

Resources

Read More

0
Subscribe to my newsletter

Read articles from Pagepro directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Pagepro
Pagepro

React, React Native, and Jamstack developers for hire! At Pagepro, we overtake the technical duties by providing React and React Native development teams, so you can focus on strategic goals of your business, and stop worrying about the delivery so much.