Creating a starter project with Next.js, TypeScript, Sanity Studio v3, and ChakraUI
Learn how to create a starter project that uses Next.js, TypeScript, Sanity Studio v3, and Chakra-UI. Feel free to replace Chakra-UI with any other component library, or remove it completely!
By Chris Jardine
December 7, 2022
Learn how to create a starter project with Next.js, TypeScript, Sanity Studio v3, and Chakra-UI. This guide assumes you already know how to use Next.js.
Feel free to use any other component library or technology, if any, for your front end. Chakra-UI is great, but other options include Material Design, Mantine, AntD, and PrimeReact. If you want something less opinionated and prefer styling with class names over props, TailwindCSS mixed with Headless UI is awesome, too.
Next.js
To start, create a new Next.js project:
npx create-next-app@latest
Give the project a name, such as next-sanity-chakra-starter.
The next two prompts ask if you want to use TypeScript and ESLint. Select yes for both prompts.
Once complete, open the project in VS Code:
cd next-sanity-chakra-starter
code .
Optional: If you're adding TypeScript to an existing project
If you're following this guide with an existing project, create a file called tsconfig.json
at the root of your project. When you run npm run dev
, installation instructions will be shown to set up TypeScript. Once done, change your .js
files to .ts
and your .jsx
files to .tsx
.
Note: depending on your setup, you may not be able to convert some config files. That's fine, just leave them as they were.
Optional: Configure ESLint, TypeScript ESLint, and Prettier
This is optional, but I highly recommend that you don't skip this step. You'll be glad to have them set up. I have a separate article outlining how to do this, which you can find here.
Cleanup
When I start a new project, the first thing I like to do is remove the unnecessary boilerplate provided by Next.js. Fortunately, there's a lot less than there used to be.
- Delete everything from
pages/index.tsx
, leaving only an emptydiv
. Personally, I prefer using arrow functions, so I delete everything and create a new arrow function. - If you're using Chakra-UI or some other component library, you won't need CSS modules. You can delete
styles/Home.module.css
. - Repeat step 1 with
pages/_app.tsx
.
Depending on the version of Next.js you're using, you may also have unneeded assets in the public
directory that can be deleted.
Results
If you followed along, the files we changed now look like this:
const Home = () => {
return <div></div>;
};
export default Home;
import '../styles/globals.css';
import type { AppProps } from 'next/app';
const App = ({ Component, pageProps }: AppProps) => {
return <Component {...pageProps} />;
};
export default App;
Sanity Studio v3
The great thing about Sanity Studio v3 is that we can embed the Studio directly in our Next.js project rather than running it on a separate server. Unfortunately, I've not come across a way to create Sanity projects without having it output a project, so we have to do that and then delete the project. Make sure to follow along though, as there are a couple files we're going to take from the output project first just to make our lives a little easier.
Create a new Sanity project
Since Sanity Studio v3 isn't officially released, we need to install it with the @dev-preview
tag:
npm create sanity@dev-preview
Follow the steps:
Login type
: Log in using whichever provider you used to create your Sanity account. If you don't have one, create one first here.Select project to use
: We want to create a new project. I named minekeplux-blog
since I'm going to be building off this starter to create this blog :)Use the default dataset configuration: yes
Project output path
: Just use the preset output path because we'll be deleting it anyway.Select project template: Clean project with no predefined schemas
Do you want to use TypeScript? Yes
Package manager to use for installing dependencies: npm
You'll now have a new directory in your project with the name of whatever you chose for the name is step 4.
Fix the project structure
Create a src
directory at the root of your project and another directory inside it called studio
. From the generated project, move the schemas
and static
directories into your new src/studio
directory. Move the sanity.cli.ts
and sanity.config.ts
files at the root of your project there as well.
Now you can delete the rest of the generated Sanity folder. Your project should now contain the following structure:
...
+- src
| +- studio
| +- schemas
| +- index.ts
| +- static
| +- .gitkeep
| +- sanity.cli.ts
| +- sanity.config.ts
...
Install required dependencies
If you checked out the package.json
file in the project we deleted, you probably noticed that it included some dependencies that we don't have. We need them, so install them now:
npm i sanity@dev-preview next-sanity @sanity/image-url @portabletext/react react-is styled-components
npm i -D @sanity/eslint-config-studio
Next, add @sanity/eslint-config-studio
to the extends
property of your ESLint configuration file.
Finally, open sanity.config.ts
and add basePath: '/studio'
in the configuration object. This is the route we use to access the Studio in the browser. Feel free to adjust it if you want.
Create a Sanity client
To be able to query Sanity, we need to have a client configured with our project details. We'll use the next-sanity
package for this, which includes a createClient
function.
Create a new file: src/studio/client.ts
. I like to keep everything Sanity related here, but feel free to move things around in a way that fits your structure.
Add the following to the file:
src/studio/client.ts
import { createClient } from 'next-sanity';
import config from '../../../sanity.config';
export const client = createClient({
...config,
useCdn: true,
apiVersion: '2022-03-13',
});
ts
The createClient
function takes in an object of type ClientConfig
. We spread our previously created configuration file in the object and add the useCdn
and apiVersion
properties.
useCdn
is an optional, but recommended, option that will allow Sanity to respond with cached data, which results in faster performance . You can read more about it here.
apiVersion
is optional, but highly recommended and will result in a warning if it's not set. Simply put, set it to the date that you start your project. Your project will use the API in its state from that date, so future updates to the API won't mess up your project.
The client can now be used to make requests!
Create a route for the Studio
This part makes use of dynamic routing in Next.js. Since the basePath
was previously define as /studio
, we need to create a new directory in the pages
directory called studio
.
Ultimately, the Studio will generate many routes and it's impossible to hardcode them. Next.js makes this super easy to handle. All we need to do is create a single file inside the pages/studio
directory called [[...index]].tsx
. This weird filename is known as an optional catch-all route. The optional part ensures that the base route at /studio
is handled in addition to /studio/some/random/sub-route
and any other route the Studio comes up with.
In the route file, add the following code:
pages/studio/[[...index]].tsx
import { NextStudio } from 'next-sanity/studio';
import sanityConfig from '../../sanity.config';
const StudioPage = () => {
return <NextStudio config={sanityConfig} />;
};
export default StudioPage;
tsx
Test it out
We can now access the Studio at http://localhost:3000/studio
. Go ahead and run your project:
npm run dev
If you see an error about @sanity/ui
, delete your node_modules
directory and package-lock.json
file. Then reinstall your dependencies with npm i
.
CorsOriginError
If you get here, great! Chances are, you've seen several variations of CORS-related errors in the past. They can be annoying and frustrating to fix, but this one is easy!
When you create a new Sanity project, Sanity automatically creates a CORS origin host at http://localhost:3333
. If you've used Sanity before, you know that's where you'd normally access your Studio. In our case, we're no longer running a separate server because the Studio is built right into our project. So, unless you've changed it, you Next.js project should be running on port 3000
.
So, how do you fix it?
All you have to do is go to your project's API settings at https://www.sanity.io. Under CORS origins, you can delete http://localhost:3333
. Then, click Add CORS origin and enter http://localhost:3000
(or whatever port your Next.js server is running on). Check the box next to Allow credentials and press Save.
Now the Studio is working! You should see a note with the title No document types. Perfect!
Sanity Studio Vision Plugin
Sanity has a lot of plugins, and you can even create some of your own. That's beyond the scope of this guide, but there's one plugin we want installed on our starter project.
To be able to query our data from within the Studio, we need to add the Studio Vision plugin:
npm i --save-exact @sanity/vision@dev-preview
The @dev-preview
tag here will install the v3-ready version of the plugin.
To enable it, open sanity.config.ts
and add the Vision Tool to the plugins
array:
sanity.config.ts
import { visionTool } from '@sanity/vision';
// ... other imports
const config = defineConfig({
// ... other properties
plugins: [
// ... other plugins
visionTool({
defaultApiVersion: 'v2021-10-21',
defaultDataset: 'production'
})
]
})
ts
The defaultApiVersion
and defaultDataset
properties are optional, but make sure the values match your setup if you use them.
Now, when you go to your Studio, you should see a button labeled Vision next to the Desk button.
Final Notes
At this point, the starter can be pushed to GitHub and be cloned. To clean things up a bit, go to the sanity.cli.ts
and sanity.config.ts
files and set the projectId
and dataset
properties to empty strings. These will need to match the Sanity project being worked on, so there's no sense in leaving your project's settings in the public repo. Don't worry if you accidentally commit your projectId
and dataset
, though, as they're considered publicly accessible anyway.
To use the starter, I would use the following process:
- Clone the repo.
- Install dependencies with
npm i
. - Create a new Sanity project with
npx create sanity@dev-preview
. - Delete the generated project.
- Update the CORS origins on the Sanity website and copy the
projectId
from the interface. You should already know the dataset name, but you can also find that on the website. Enter those values intosanity.cli.ts
andsanity.config.ts
.
Chakra-UI
This part is easy, but I like to include it in my starter so I don't have to do it every time.
Install required dependencies
npm i @chakra-ui/react @emotion/react @emotion/styles framer-motion
Wrap the App with ChakraProvider
Go into /pages/_app.tsx
and wrap your app with the ChakraProvider
component:
/pages/_app.tsx
import { ChakraProvider } from '@chakra-ui/react';
import type { AppProps } from 'next/app';
import '../styles/globals.css';
const App = ({ Component, pageProps }: AppProps) => {
return (
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
);
};
export default App;
tsx
Latest posts
Content modeling with Sanity schemas
January 25, 2023
Configuring ESLint and Prettier in Next.js with TypeScript
December 4, 2022