Join us live Sept. 27 – How Sanity and Vercel powered Morning Brew's transformation –>

Event directory schemas

By Nick Borrett

Schemas for creating an event directory on Sanity

Event

// event.js

export default {
  name: "event",
  title: "Event",
  type: "document",
  description: "An event",
  fields: [
    {
      name: "name",
      title: "Name",
      type: "string",
      validation: (Rule) => Rule.required(),
    },
    {
      name: "summary",
      title: "Summary",
      type: "text",
      description:
        "A short summary of the event, no more than 2 or 3 sentences",
    },
    {
      name: "description",
      title: "Description",
      type: "array",
      of: [
        {
          type: "block",
        },
      ],
      description: "A full description of the event",
      validation: (Rule) => Rule.required(),
    },
    {
      name: "start",
      title: "Start date",
      type: "datetime",
      validation: (Rule) => Rule.required(),
    },
    {
      name: "end",
      title: "End date",
      type: "datetime",
      validation: (Rule) => Rule.required(),
    },
    {
      name: "image",
      title: "Image",
      type: "image",
      description: "An image relevant to the event",
    },
    {
      name: "url",
      title: "URL",
      type: "url",
      description: "The homepage of the event",
    },
    {
      name: "category",
      title: "Category",
      type: "category",
    },
    {
      name: "organizer",
      title: "Organizer",
      type: "reference",
      to: [
        {
          type: "organizer",
        },
      ],
    },
    {
      name: "venue",
      title: "Venue",
      type: "reference",
      to: [
        {
          type: "venue",
        },
      ],
    },
    {
      name: "slug",
      title: "Slug",
      type: "slug",
      options: {
        source: "name",
      },
      description: "This can be used to identify the event in a URL",
    },
  ],
  orderings: [
    {
      title: "Event name",
      name: "eventNameAsc",
      by: [{ field: "name", direction: "asc" }],
    },
    {
      title: "Event date",
      name: "eventDateDesc",
      by: [{ field: "date", direction: "desc" }],
    },
  ],
  preview: {
    select: {
      title: "name",
      subtitle: "organizer.name",
      media: "image",
    },
  },
};

Category

// category.js

const categories = [
  { value: "Art", title: "Art" },
  { value: "Causes", title: "Causes" },
  { value: "Comedy", title: "Comedy" },
  { value: "Crafts", title: "Crafts" },
  { value: "Dance", title: "Dance" },
  { value: "Drinks", title: "Drinks" },
  { value: "Film", title: "Film" },
  { value: "Fitness", title: "Fitness" },
  { value: "Food", title: "Food" },
  { value: "Games", title: "Games" },
  { value: "Gardening", title: "Gardening" },
  { value: "Health", title: "Health" },
  { value: "Home", title: "Home" },
  { value: "Literature", title: "Literature" },
  { value: "Music", title: "Music" },
  { value: "Networking", title: "Networking" },
  { value: "Party", title: "Party" },
  { value: "Religion", title: "Religion" },
  { value: "Shopping", title: "Shopping" },
  { value: "Sports", title: "Sports" },
  { value: "Theatre", title: "Theatre" },
  { value: "Wellness", title: "Wellness" },
];

export default {
  name: "category",
  title: "Category",
  type: "string",
  options: {
    list: categories,
  },
};

Organizer

// organiser.js

export default {
  name: "organizer",
  title: "Organizer",
  type: "document",
  description: "An organizer",
  fields: [
    {
      name: "name",
      title: "Name",
      type: "string",
      validation: (Rule) => Rule.required(),
    },
    {
      name: "logo",
      title: "Logo",
      type: "image",
    },
  ],
};

Venue

// venue.js

export default {
  name: "venue",
  title: "Venue",
  type: "document",
  description: "A venue",
  fields: [
    {
      name: "name",
      title: "Name",
      type: "string",
      validation: (Rule) => Rule.required(),
    },
    {
      name: "address",
      title: "Address",
      type: "object",
      fields: [
        { name: "address1", type: "string", title: "Address 1" },
        { name: "address2", type: "string", title: "Address 2" },
        { name: "city", type: "string", title: "City" },
        { name: "region", type: "string", title: "Region" },
        { name: "postalCode", type: "string", title: "Postal code" },
      ],
    },
    {
      name: "coordinates",
      title: "Coordinates",
      type: "geopoint",
      description:
        "This can be used to display the location of the venue when using a mapping service",
    },
  ],
  preview: {
    select: {
      title: "name",
      address: "address",
    },
    prepare(selection) {
      const { title, address } = selection;

      const formattedAddress = Object.keys(address)
        .map((key) => address[key])
        .filter((e) => e.trim().length > 0)
        .join(", ");

      return {
        title: title,
        subtitle: formattedAddress,
      };
    },
  },
};

These schemas can be used to build a simple event directory by creating the following document types: Event, Organizer and Venue. This allows an Event to be created, linked to an optional Organizer and an optional Venue. Most fields are optional, but validation can easily be added depending on your use cases. Together with these document types, there is a Category field with a preset list of categories, used by the Event document type.

Contributor