Visual Editing with Next.js App Router and Sanity Studio
Setup "Live by Default" fetches and interactive live preview with Presentation in Sanity Studio
Go to Visual Editing with Next.js App Router and Sanity StudioHow to get started with the Nuxt.js and Sanity.io powered event website
If you have followed the steps for the landing page template on sanity.io/create you should now have the project code on your account on GitHub, as well as a editing environment and a Nuxt.js frontend deployed on Netlify. This tutorial will first introduce you to the stack, and walk you through how to customize this project to make it your own by demonstrating:
You can safely skip this section if you're already familiar with Sanity, Nuxt.js and Netlify.
Nuxt.js is a Vue-framework that makes it easier to make a web application with server-rendering, code-splitting for faster page-loads, and client-side routing, while being highly customizeable and compatible with many setups.
Netlify is a service that lets you easily build and deploy websites from Git. If you use a static site generator, Netlify can build the site before making it available on a global scaleable network. You can also host Single Page Applications on Netlify, like we do with Sanity Studio in this template.
Sanity.io is where you create, store, and mange your structured content. When you create a new project with this template we will put the customizeable editing environment in the GitHub repository along with the code for the frontend. The content types and the input fields are configured with simple JavaScript objects, and you can optionally inject your own React components if you want to extend the Studio further.
The Studio connects the hosted APIs. Those are built to make it possible to integrate almost any application or service. The Studio let's you read and write content to it, while the blog mainly reads content from it, and fetches optimized images from the asset API. It's good to know that even if you can run the Studio locally while you develop, the content is always synced in real-time to the cloud.
The code for the website, as well as Sanity Studio is added as a monorepo on the GitHub account you chose when creating the project. You can find links to this repository on your dashboard and email that we sent you. You should also be able to find it if you go to the repositories overview on your user page.
Use your prefered git tool to clone the repository to where you want to work with it locally.
When you have the code on your machine, open the project folder in the command line and install dependencies for the whole project:
~/sanity-nuxt-events
> npm install
This will install dependencies for both the web frontend and the studio. You can also start the development servers for both in parallell by running the following in the project’s root folder:
~/sanity-nuxt-events
> npm run dev
Both Nuxt.js and the Sanity Studio use Hot Module Reloading when you make changes in the code for them. There are certain situations where you have to restart the development servers in order to load changes, for example if you add extra dependencies from npm.
Let's say we want to add a list of social media links for the people involved in this event. In this example we'll add these as predefined keys (although you could have implemented it as a generic key-value-array).
First we'll add a new object type for social
beginning with adding a new file called social.js to /studio/schemas/objects/
:
// social.js
export default {
name: 'social',
type: 'object',
title: 'Social Media Links',
fields: [
{
name: 'twitter',
type: 'url',
title: 'Twitter',
description: 'The URL for the Twitter profile'
},
{
name: 'instagram',
type: 'url',
title: 'Instagram',
description: 'The URL for the Instagram profile'
},
{
name: 'github',
type: 'url',
title: 'GitHub',
description: 'The URL for the GitHub profile'
},
{
name: 'linkedIn',
type: 'url',
title: 'LinkedIn',
description: 'The URL for the LinkedIn profile'
},
{
name: 'website',
type: 'url',
title: 'Website',
description: 'The URL for the website'
}
]
}
You are of course free to add other / more services if you want. You can also see that this configuration is a repetative. Just to show what's possible, let's generate the exact schema in a slightly different way:
// social.js
const services = ['twitter', 'instagram', 'github', 'linkedIn']
export default {
name: 'social',
type: 'document',
title: 'Social Media Links',
/**
* Loop through the array of service keys, and return the field configuration.
* The title will be generated from `name`
* */
fields: services
.map(name => ({
name,
type: 'url',
description: `The full URL to the ${name} profile`
}))
.concat({
name: 'website',
type: 'url',
title: 'Website',
description: 'The URL for the website'
})
}
Choose the approach you prefer and save the changes. Now you can include this new object type in /studio/schemas/schema.js
like this:
// schema.js
// ...
// Document types
// ...
// Object types
// ...
import social from './objects/social'
// Then we give our schema to the builder and provide the result to Sanity
export default createSchema({
name: 'event',
// Then proceed to concatenate our our document type
// to the ones provided by any plugins that are installed
types: schemaTypes.concat([
// ... the other types,
social
])
})
Now we should be able to use this field by refering to type: 'social'
elsewhere in the schema. What we did now was to “hoist an object type”. This is required to be compatible with Sanity’s GraphQL API if you want to deploy that later (not required for this project).
The code for adding these fields to the speakers, i.e. the person document type located at /studio/schemas/documents/person.js
looks like this:
// person.js
export default {
type: 'document',
name: 'person',
title: 'Person',
fields: [
{
name: 'name',
title: 'Name',
type: 'string'
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
description: 'Some frontends will require a slug to be set to be able to show the person',
options: {
source: 'name',
maxLength: 96
}
},
{
name: 'image',
title: 'Image',
type: 'mainImage'
},
{
name: 'bio',
type: 'bioPortableText',
title: 'Biography'
},
{
name: 'social',
type: 'social',
title: 'Social media links'
}
],
preview: {
select: {
title: 'name',
subtitle: 'slug.current',
media: 'image'
}
}
}
The editor for Person in the studio should look like this:
Make sure to add some content in the different fields yourself, and remember to hit the blue Publish button to make the changes available in the public API.
If you aren't familiar with Vue or Nuxt, this might be a good time to bookmark their documentation (Nuxt, Vue). We'll try to make sure that you can tag along this tutorial though.
What we want to do now is to add these links to the page template for speakers. That's located at the /web/pages/speakers/_slug.vue
.
With Nuxt comes a method called asyncData
that lets it fetch data on the server before the markup is sent to the client. If you look at this code in the template file, you'll find this code sanityClient.fetch(query,params)
where the query is defined as groq`[_type=="person"&&slug.current==$slug][0]{..., "id":_id}`
. This is a GROQ query, which is one of the way you can interact with your content from Sanity’s backend. You don't actually need to do anything with the query, but it might be interesting to understand what's going on. Here's how you should read it:
*
<= Select all the documents in your project
[ ]
<= filter them down by the criteria inside these brackets
_type == "person" && slug.current == $slug
<= select only document that has a _type
which is person
and where the current slug is the same as the $slug
parameter.
{ }
<= Project the fields in those documents to whatever is defined i
"id: _id
<= make a new key in the outcoming document object called id
and ascribe the value of its field _id
to it.
The reason that you don't need to specify the new social
field, is that it's automatically included with the ...
operator.
If you want to play more with GROQ you can also install the query explorer by running the CLI command sanity install @sanity/vision
in your /studio
folder.
We will just show you add some really plain markup and let you decide how you want to style it, or if you want to add icons or use some Vue package for outputting these links.
// web/pages/speakers/_slug.vue
<template>
<section class="container">
<SanityImage
:v-if="image.asset"
:image="image"
:height="1200"
:width="1200"
class="image"
/>
<h1 class="title">{{ name }}</h1>
<div class="bio" :v-if="bio.length > 0">
<BlockContent v-if="bio" :blocks="bio" />
</div>
<div class="social">
<ul v-if="social">
<li v-if="social.twitter"><a :href="social.twitter">Twitter</a></li>
<li v-if="social.instagram">
<a :href="social.instagram">Instagram</a>
</li>
<li v-if="social.github"><a :href="social.github">Github</a></li>
<li v-if="social.linkedin"><a :href="social.linkedin">LinkedIn</a></li>
<li v-if="social.website"><a :href="social.website">Website</a></li>
</ul>
</div>
<div v-if="scheduleItems" class="sessions">
<h2>Sessions</h2>
<SessionItem
v-for="scheduleItem in scheduleItems"
:key="scheduleItem._key"
:schedule-item="scheduleItem"
/>
</div>
</section>
</template>
We use the v-if directive to make sure the link(s) doesn't render if there's no data.
Now you should commit the changes to git and push them to the remote repository on GitHub (usually git push origin master
). Netlify watches changes on master
and will redeploy the studio and the landing page site. This usually takes a few minutes.
This is only the start of course! There's loads of things you can do to take this landing page website further. Check out our documentation and blog for more, and make sure to join our community on Slack to get help and see what other people are doing with Sanity.
Sanity Composable Content Cloud is the headless CMS that gives you (and your team) a content backend to drive websites and applications with modern tooling. It offers a real-time editing environment for content creators that’s easy to configure but designed to be customized with JavaScript and React when needed. With the hosted document store, you query content freely and easily integrate with any framework or data source to distribute and enrich content.
Sanity scales from weekend projects to enterprise needs and is used by companies like Puma, AT&T, Burger King, Tata, and Figma.
Setup "Live by Default" fetches and interactive live preview with Presentation in Sanity Studio
Go to Visual Editing with Next.js App Router and Sanity StudioA complete guide to setting up your blog using Astro and Sanity
Go to Build your blog with Astro and SanityThis guide teaches how to add a custom input component to a field for Sanity Studio v3
Go to How to build an input component for Sanity Studio v3A thorough intro to using GROQ-projections in a webhook contest
Go to GROQ-Powered Webhooks – Intro to Projections