Sanity

The Revolutionary Content Management System (CMS)

Introduced in the 2023-2024 academic year, Sanity is a content management system that has made the process of uploading and maintaining the content on our websites much easier. Sanity provides a TypeScript client that we use to pull from our content database and render that onto our webpage.

Setup

The following environment variables are required in order to get Sanity to pull data from our content database:

  • NEXT_PUBLIC_SANITY_PROJECT_ID

  • NEXT_PUBLIC_SANITY_DATASET

  • NEXT_PUBLIC_SANITY_API_VERSION

Schemas

Schemas describe the different types of content we plan on showing in our application. For example, the FAQ section on the home page relies on an FAQ schema. Specifically, when creating an FAQ, a developer would go to http://localhost:3333 in the development environment (or https://content.irvinehacks.com on production), click on FAQs, click the first item in the list that appears, and then add an item.

A view of the FAQs in Sanity

Note that we use this structure to allow custom ordering of the FAQs. Otherwise, we would need to take a more complicated approach for custom sorting, such as creating a field in the schema dedicated to specifying order.

The code for the FAQ schema is relatively simple:

import { defineType, defineField, defineArrayMember } from "sanity";
import { toPlainText } from "@portabletext/react";
import { FileQuestion } from "lucide-react";

export default defineType({
	name: "faqs",
	title: "FAQs",
	type: "document",
	icon: FileQuestion,
	fields: [
		defineField({
			name: "faqs",
			title: "FAQs",
			type: "array",
			of: [
				defineArrayMember({
					type: "object",
					name: "faq",
					fields: [
						defineField({
							name: "question",
							title: "Question",
							type: "text",
						}),
						defineField({
							name: "answer",
							title: "Answer",
							type: "array",
							of: [
								defineArrayMember({
									type: "block",
									styles: [
										{ title: "Normal", value: "normal" },
									],
									lists: [],
								}),
							],
						}),
					],
				}),
			],
		}),
	],
});

This is a simplified version of what is actually being used, but it should be clear that there is a field asking for what the FAQ is and another field asking for the answer for that FAQ.

GROQ Queries

To query the content from the database from our frontend, we use the TypeScript client mentioned at the top of the page. Specifically, we create a client, specifying all the necessary environment variables and pass in GROQ queries to fetch content. The query to fetch all FAQs would be:

await client.fetch("*[_type == 'faqs']")

Zod

To validate the types in the data that is queried from Sanity, we use Zod, a TypeScript schema validation library. We can declare our own Zod schema and use it to parse the data returned from Sanity. See getQuestions.ts in the FAQ/ directory for an example on how to do this.

Last updated