Best approach for parent/child relationships and slugs in Sanity.io

1 replies
Last updated: Jun 22, 2023
Hello, I've got a page document type which uses structured content for page building just pretty simple stuff for now. What I can't seem to figure out is the best way to approach parent / child relationships. I have a slug field like this
defineField({
  name: "slug",
  type: "slug",
  options: { source: "title" },
  group: "content",
}),
What I need to achieve is setting the relation and get the slug like the below.

Home
/
About
about
Guides
guides
> How To Play
guides/how-to-play
Slots
slots
> Best Slots
slots/best-slots

I can set the relation field but not sure on best approach for the slugs. If I manually set the Best Slots slug to be
slots/best-slots
in sanity studio it only comes through as
best-slots
are there any good guides on this?
Thanks
Jun 20, 2023, 4:30 PM
You could define a “parent” field for each document, like this
	defineField({
		name: 'parent',
		title: 'Kategori',
		type: 'reference',
		to: [{ type: "article" }],
	}),
Then have your slug field call a custom slugifier, like this:

	defineField({
		name: 'slug',
		title: 'URL',
	  	type: 'slug',
		options: {
			source: (doc, options) => ({ doc, options }),
			slugify: asyncSlugifier
		},
	}),
My slugifier function looks like this (slugifier.ts):


// Look up the slug of the parent category and append it to the slug of the current document
export async function asyncSlugifier(input: { doc: { title: string; parent: { _ref: string } } }, schemaType: any, context: any) {

	const {getClient} = context
	const client = getClient({apiVersion: '2023-03-01'})

	let pageSlug = input.doc.title
		.toLowerCase()
		.replace(/\s+/g, '-') // slugify the title
		.slice(0, 200);

	// Remove all non-alphanumeric characters (but keep the hyphens)
	pageSlug = pageSlug.replace(/[^A-Za-z0-9-]/g, '');

	if (input.doc.parent) {
		const query = '*[_id == $parentID]';
		const params = {parentID: input.doc.parent._ref}

		var result = await client.fetch(query, params);

		if (result.length > 0) {
			let parentSlug = result[0].slug.current;
			return `${parentSlug}/${pageSlug}`;
		} else {
			return pageSlug;
		}
	} else {
		return pageSlug;
	}	
}
This looks up the slug of the parent, and prepends that to the slugified title of the current document to make a new URL. This will work as long as the parent has it’s slug set correctly.
Jun 22, 2023, 8:02 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?