Chris Jardine
Next.js
Sanity
TypeScript
ChakraUI
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.
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 .
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.
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.
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.
pages/index.tsx
, leaving only an empty div
. Personally, I prefer using arrow functions, so I delete everything and create a new arrow function.styles/Home.module.css
.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.
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;
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.
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 mine keplux-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.
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
...
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.
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!
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
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
.
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 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.
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:
npm i
.npx create sanity@dev-preview
.projectId
from the interface. You should already know the dataset name, but you can also find that on the website. Enter those values into sanity.cli.ts
and sanity.config.ts
.This part is easy, but I like to include it in my starter so I don't have to do it every time.
npm i @chakra-ui/react @emotion/react @emotion/styles framer-motion
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
Chris Jardine
I'm a full-stack developer and the owner of Keplux Development. I love learning about web development and teaching others what I know.
Be the first to comment!
About
Keplux Development is a web design and development agency in Toledo, OH. We provide custom web design and development services, ecommerce websites, search engine optimization, website hosting and maintenance, and more.