1 of 54

Building Blazing-Fast Websites with Next.js & Sanity.io

2 of 54

Hello Everyone!

3 of 54

Table of Contents

01 Intro

  • What are we building?
  • What is headless architecture?
  • Introducing platforms & tools
    • CMS: Sanity.io
    • Site building: Next.js
    • Deployment: Vercel
    • UI Component Env: Storybook

02 Setting up the Repo

  • Forking, cloning, dev scripts, quick walkthrough

� 10m pause: Set up your repo!

03 Setting up Sanity.io

  • Content modeling
  • Defining schemas & fields�

10m pause: Set up your Sanity account!�

  • Hands-on (Breakout Rooms)
    • 20m: Configure a page schema
    • 20m: Define a Media Module schema
    • 10m: Populate Sanity with content�
  • Querying with GROQ

04 Setting up Next.js

  • Dynamic routing
  • Querying Sanity data & fetching page content
  • Static page builder�
  • Hands on (Breakout room)
    • 30m: Render components on the page

05 Deploying to production on Vercel

  • New project set up, ENV variables, & webhooks
  • Hands-on (Breakout Rooms)
    • 10m: Deploy to production!
    • 10m: Customize your site

4 of 54

What are we building?

5 of 54

6 of 54

7 of 54

What is headless architecture?

8 of 54

What is headless architecture?

In headless architecture, the presentation layer is decoupled from the content layer. The content is served from a CMS via an API, and can be accessed by a wide variety of frontend solutions.

A headless platform can be broken down into two parts:�

  1. The CMS where content authors can manage website content through an editor interface. (Sanity, Contentful, etc.)�
  2. The site builder, which includes a front-end framework (like Next.js, Gatsby, etc.), a component library, and page templates. The site builder combines your content and React components into an ultra-fast application.�

9 of 54

Benefits of going headless

  • It’s framework agnostic – developers can build the presentation layer using tools of their choice.�
  • Highly customizable, with the ability to bring in your own components and third party libraries (search, personalization and analytics).�
  • Headless CMS tools optimize for SEO and performance, usually by leveraging Static Site Generation (SSG) or Server Side Rendering (SSR).�
  • The same content can be used across all of your different channels and digital touchpoints.

10 of 54

Headless architecture - a visual journey

11 of 54

Headless architecture - the CMS workflow

12 of 54

Introducing �platforms & tools

13 of 54

Sanity

  • Is a flexible, API-based headless CMS designed to empower developers in building modern websites.�
  • Developers can leverage the Sanity APIs to retrieve and manipulate content, integrating with any front-end framework – in our case, React.�
  • Content creators can easily add, edit, and organize content through a user-friendly interface, and live preview their changes.�
  • Empowers React developers to build headless websites with Next.js!

14 of 54

Next.js

  • Is a React framework that empowers developers with server-side rendering, static site generation (SSG), and dynamic routing.�
  • Content APIs (like Sanity’s) serve as the data source, while Next.js handles the presentation and rendering.
  • Unlike with React on its own, with Next.js & SSG, the HTML pages are generated and the content is bundled at build time, cached in multiple servers globally, and delivered by the CDN closest to each user. This makes Next applications ultra-performant.

15 of 54

Vercel

  • Is a cloud platform that revolutionizes the deployment and hosting experience for Next.js applications. Minimal config needed!
  • Leverages features like SSR, SSG, and ISR.�
  • Allows the creation of serverless functions and API routes within Next.js applications.�
  • Provides built-in performance monitoring and tracking tools.

16 of 54

Storybook

  • Is an open-source tool that allows developers to build, visualize, test, and document UI components in isolation. �
  • Provides a dedicated, interactive environment for showcasing components independently of the application they’re used in.�
  • Integrates seamlessly with popular frontend frameworks like React.�
  • Is great for rapid prototyping of new ideas without the need for a full application setup.

17 of 54

Let’s get STARTED!

18 of 54

Hands on: Set up the repo [10min]

Workshop starter repo: https://github.com/rangle/headless-workshop

  • Fork the repo into your own GitHub
  • Clone the forked version
  • Run ‘npm install’
  • Run the project locally:
    • Storybook: npm run storybook �@ localhost:6006
    • App/Sanity: npm run dev �@ localhost:3000 & *localhost:3000/studio

�*Running Sanity Studio won’t work until after we set it up!

[Screenshot of starter Sanity studio]

19 of 54

Setting up Sanity.io

20 of 54

What is a content model?

Types of Content Models

  1. Page mirrors page structure
  2. Page Module mirrors the components �(ie: Hero Component)
  3. Data Object mirrors misc. data that may be used anywhere on the site (ie: SEO)

When working in any headless CMS we’re in charge of building the authoring interface. A content model is a way for us to define and “model” that interface. In Sanity, we achieve this by creating a “schema”, which acts as the blueprint for the content model.

21 of 54

Content Model: Page

A page is a content model that mirrors the information needed to put together a single page. It usually contains two different types of content:

  1. Metadata
    1. Slug to define the url of the page
    2. SEO-related content such as title, meta description, meta image
  2. Page layout
    • Content that is rendered on the page
    • Order of the components on the page

22 of 54

Content Model: Page Module

A page module is what's displayed on the page. This content model mirrors the information needed for a single component we want to display on a page. Content authors add page modules to a page and enter data in input fields within the CMS.

23 of 54

Defining a Schema

Content models are defined by creating schemas using Sanity’s specific syntax.

  • Name can be considered the equivalent of a chosen ID for the content model.
  • Title is the displayed tile in the Sanity interface.
  • Fields are the authoring fields in the Sanity interface.
  • defineField and defineType function are optional but they are helpful to provide type check.

24 of 54

Schema Types: Document vs. Object

Document

  • Parent schema type, all the other types you may define live inside the documents.
  • Can be queried
  • When modeling for a website, the document is used to create the “Page” content model

Object

  • Use it to define custom types that has fields of strings, numbers, arrays as well as other object types.
  • Cannot be queried
  • We use this to model our Components in the Sanity interface

In Sanity, we will be using the document and object schema types to define our Page and Page Module content models.

25 of 54

Defining a field

  1. Field Types are used to define what kind of input is displayed in the Sanity interface
  2. Additional configuration can be added to each field
    1. Validation
    2. Initial values

Schema Documentation: https://www.sanity.io/docs/schema-types

26 of 54

Field Examples

Displayed name in Sanity Interface

Renders the toggle input field

Defines the field validation

Renders the text input field

27 of 54

Matching “name” to component and props name

  • Name of schema needs to match component name
  • Name of fields needs to match prop name

* We’ll revisit this in the next section to learn why this is necessary

28 of 54

Schema Demo

29 of 54

Setting up the Sanity Studio

  1. Create a Sanity account: https://www.sanity.io/get-started
  2. A new project should now be available in your Sanity dashboard: https://www.sanity.io/manage

⚠️ Do not follow instructions to install Studio in the CLI! ⚠️

Your Account

Click to exit. Do not follow instructions to install Studio in CLI.

30 of 54

Accessing the Studio locally

  • Rename the env.local.example file to env.local. Then, within that file:
    1. NEXT_PUBLIC_SANITY_PROJECT_ID can be found in the project dashboard�
    2. Create a Sanity Read Token by navigating to the API tab → Tokens�
  • Access the studio locally:
    • Start the Nextjs app by running `npm run dev`
    • Navigate to “localhost:3000/studio”�
    • Accept the prompt to add CORS to your Sanity project

31 of 54

Hands on: Setting up Sanity studio [10m]

See previous 2 slides for detailed instructions!�

  1. Sign up for a new Sanity account
  2. Create a new project
  3. Configure env.local

Result: You should be able to navigate to localhost:3000/studio and see the Sanity Studio!

32 of 54

Hands on: Requirements for Page schema [20min]

  • Navigate to sanity > schemas > documents folder, a page.ts has already been started!
  • Configure the below fields:

Result: You should be able to see Pages in Sanity Studio and be able to add content to it

*** Reference Schema Documentation: https://www.sanity.io/docs/schema-types

BONUS: Add a custom validation to the slug field to ensure all slugs start with a leading ‘/’

Title (DONE)

      • Type: string
      • Required

Slug

      • Type: slug
      • Required

Sections

      • Type: array
      • Required
      • We have prebuilt schemas for you, let’s add them to this array
        • Hero, CTA Banner, Featured Items, Featured Text, Quote
        • HINT: you can directly reference other schemas by referencing the schema “name” in the “type” property

33 of 54

Hands on: Requirements for Media Module schema [20min]

  • Add a new file in the schema > object folder, type needs to be object
  • Configure fields (field type can be determined by looking at the component):
    • Heading
    • Body
    • Image On Right
    • Image
    • Image alt
    • Is Dark
  • Import into sanity.config.ts and add to Page schema

BONUS: Customize the preview to feature heading field as title, ‘Media Module' as subtitle and image as media

***Remember that the name of the schema must match the name of the component and the name of the fields must match the component props.

Result: You should be able to add the Media Module onto a Page in Sanity Studio. You should see the component properly render in the Preview

34 of 54

Hands on: Add some content! [10min]

We want to populate Sanity with some data so we can test it out in the next section. Don’t worry about filling in everything at this point!

  1. Homepage
    1. Slug = /
    2. Add one component in there!
  2. Service landing page
    • Slug = /services
    • Add one component in there!
  3. Service page
    • Slug = /services/garden-design
    • Add one component in there!
  1. Add some links into the nav and footer
  2. Don’t forget to publish your changes!

* You will not be able to preview this content on the site – YET!

***Make sure to include the leading slashes for slugs!

35 of 54

Querying Data with GROQ

  • GROQ is Sanity's open-source query language, similar to GraphQL but even more flexible and powerful
  • We can test our queries in the “Vision” table in Sanity Studio
  • Cheat sheet: https://www.sanity.io/docs/query-cheat-sheet

36 of 54

Anatomy of a GROQ query

Select all documents where “_type” is equal to “page”

Only return the “slug.current” value as “slug” in the document object

Select all “page” documents with “slug.current” equal to “/”

Return all values from the document object

37 of 54

Setting up Next.js

38 of 54

Routing

  • Next.js has a file-system based router
  • When a file is added to the pages directory, it's automatically available as a route.
  • Dynamic routes
    • [fileName].tsx: this is a dynamic route segment. It will create the /services route but not /services/garden-design route. (e.g. [slug].tsx)
    • [...fileName].tsx: dynamic segments can be extended to catch-all subsequent segments by adding an ellipsis inside the brackets. It will create the /services route and /services/garden-design route, but not the / route (e.g. [...slug].tsx)
    • [[...fileName]].tsx: Catch-all Segments can be made optional by including the parameter in double square brackets. It will create all routes, including the / route (e.g. ([[...slug]].tsx)

39 of 54

Catch-all vs. Optional catch-all

Only included in optional catch-all

40 of 54

Creating dynamic routes

  • We need to define a list of paths to be statically generated by using getStaticPaths function built into Next.js.
  • getStaticPaths will only run during build in production, it will not be called during runtime
  • We will fetch all page paths from Sanity and map it to this structure that Next.js is expecting

41 of 54

Querying data from Sanity

  • To fetch Sanity data in Next.js, we’ll be using the “createClient” function from the “next-sanity” library
  • We’ll need to construct the GROQ query and pass it to the “sanityClient” function

42 of 54

Fetching page content

  • The getStaticProps function tells Next.js to pre-render the page at build time using the props returned by it
  • The props will also be available to be accessed in the “_app” file
  • We will be fetching the page data from Sanity to be displayed on each page

43 of 54

Page builder

  • Used to map page JSON to React components
  • Page JSON contains information about the component type and the key and value of the props
  • We will be using the buildComponent function to construct React components using Sanity page JSON

44 of 54

Breaking down the buildComponent function

Import all modules that’s used in the CMS

Null checking “_type” property

Selecting the correct component based on “_type” value

Null checking if no valid component is selected

Returning the selected component with all other JSON value passed into it as props

45 of 54

Hands-on: Setup page template [20min]

  1. Create all page paths using Sanity page data
    1. Build out code in getStaticPaths
    2. GOTCHA: make sure your paths with multiple segments work (check: /services/garden-design)
    3. BONUS: try rewriting your own “pagePathsQuery”
  2. Fetch page data
    • BONUS: try rewriting your own “pagesBySlugQuery”

Result: You should now be able to navigate to all three of your pages. You should also be able to console.log the page prop and see the Sanity data you inputted

46 of 54

Hands-on: Render components on the page [10min]

  1. Navigate to util > buildComponent, import and add all CMS modules to the componentsMap object
  2. Import buildComponent into page template ([[...slug]].tsx)
    1. Map through the sections and display the react components on the page!
  3. Take a look at all your pages and make sure everything looks good
  4. Commit and push our changes to the main branch

Results: You should be able to see your complete page with all the content and sections you have inputted in Sanity!

47 of 54

Deploying to Production

48 of 54

Sign-up and creating a new project in Vercel

  • Sign-up for a free hobby account on Vercel (highly recommend to signup with Github)
  • Create a new project within Vercel
  • Import your existing github repo
    • If you didn’t sign up with your Github account, you will need to configure Github in this step
  • Don’t deploy, we’ll need to add in some environment variables first

49 of 54

Setting up ENV variables

  • Copy all the variables from your “env.local” file and paste them into the Environment Variables section
  • Hit deploy!

50 of 54

Setting up a webhook

  • We want Vercel to rebuild every time a change is published in Sanity
  • First, create a deploy hook in Vercel. Navigate to Settings > Git and find the Deploy Hooks section
  • Create a new deploy hook by giving it a name and setting the trigger branch to “main”
  • Copy the URL that’s generated

51 of 54

Setting up a webhook

  • Head over to Sanity and create a new webhook by navigating to API > Webhooks and clicking on “Create webhook”
  • Give it a name and paste in the Vercel URL we just generated into the “URL” field
  • Make sure you select all the triggers: Create, Update, and Delete
  • Click “Save”!

52 of 54

Hands-on: Deploy to production! [10min]

  • Create new Vercel project and connect to your project on github
  • Copy over all the ENV variables into the Vercel project
  • Generate a new Vercel deploy hook
  • Setup Sanity webhook using the generated Vercel deploy hook
    • Don’t forget to select all the triggers (Create, Update, and Delete)
  • Add production link to the Sanity dashboard by going to Settings > General Settings > Custom studio URL (Follow CORS prompts)

Results: You should now have a deployed link to your project! You should also be able to see updates in your production link when you publish changes on Sanity.

53 of 54

Hands-on: Customize the website [10min]

Using the remainder of the time left in the workshop (or on your own time after the workshop) customize the website to make it your own. Consider doing any of these things:

  • Update the tailwind.config.js to your own color palette
  • Add additional pages and customize each page with your own content
  • Try creating a new component from scratch

54 of 54

Thank you!