Guide

The Nuxt.js Event Website

Knut Melvær

Knut runs developer relations at Sanity.io.

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

  • How to download and start the project locally
  • How to add a document type
  • How to deploy changes

Project overview

You can safely skip this section if you're already familiar with Sanity, Nuxt.js and Netlify.

Nuxt.js

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.

The event website homepage

Netlify

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

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.

Get the project up and running locally

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.

You can find the link to the projects source code in the dashboard

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.

Adding social media links for speakers

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'
    })
}

Choice 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:

Social media links for persons

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.

Adding the social media to the Nuxt.js frontend

Getting to the new content data

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

Adding the markup

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.

The unstyled social media link list

Deploy the changes on Netlify

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.

Next steps…

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.