🔮 Sanity Create is here. Writing is reinvented. Try now, no developer setup

Discussion on how to structure clients and projects in Sanity, including unique slugs and references.

18 replies
Last updated: Nov 22, 2021
Morning everyone 🙂
If I wanted to create a structure like this, how would I best do it?

Clients -> Projects

Client One
   - A Cool Project
   - Project Example
   - Project X
Client Two
   - Another Project
   - Project X
   - Something Else

would include a unique slug for the client name, and
would be nested under
, again with a unique slug.
The question mark for me is I don't want one
to include projects with the same slug, as the URL would look like
so would need to be unique. However, another
could include a matching slug, as it would still be unique in this case.

- Valid
- Invalid (matches previous)
- Valid
Nov 21, 2021, 10:00 AM
It's the slugs thing I'm stuck with 🙂
Nov 21, 2021, 10:01 AM
One thought would be to a custom
function with
to add the client name to the slug, but at the moment I don't know how to directly nest
so I'm not sure how I'd do this
Nov 21, 2021, 10:04 AM
Hi chrish - there are a lot of approaches that could work and I am sure I am missing one or more, but here's my opinion on the simplest approach:

exist as documents • Each uses the default
option to maintain the uniqueness of their slug among documents of their type.
has a field called
that is an array of references to existing projects. • Your front end will have the task of building urls like
and those urls will always be unique by virtue of the fact that they are pulling unique pairs of clients and projects. In this way the "nesting" exists in the front end, but in Sanity, they are not nested in any way beyond the fact that a
document can reference any number of
documents. If you need to guarantee that every slug in your dataset is unique among all types, there is a function for that as an example in the docs:
Beyond that, if you wanted to make your
slugs contain data from
that reference them, I think you might be able to do that using some custom functions, (that would have existing documents of other types as a dependency) but it might add complexity you don't need: https://www.sanity.io/docs/slug-type#e1531d9d041b
Nov 21, 2021, 12:38 PM
user U
, thanks so much for your reply. This sounds really logical but my only question is how would I allow decks across projects to use the same slug?
— with your approach, I don't think this would be possible as it would have to be
Nov 21, 2021, 5:47 PM
Hi - so, by design the
field is required to be unique among documents of its type. If you wanted to make sure that information about the referencing
was automatically included in the slug of a
you could put this function in the
option for the slug field...
source: (doc) => {
  /* find the title of Clients who reference this Project */
  const query = `*[_type=="client" && references("${doc._id}")]{title}`

  return sanityClient.fetch(query).then((results) => {
    const client = results[0].title
    return `${client}-${doc.title}`
...but I don't think it's a good idea. It works, but it adds dependencies and chances for race conditions. (When you click the slug's
generate button you toggle the draft status of the document, and you would have to make sure to click "Publish" before you generate again. If you change a Client's
the related slugs would stop matching the pattern until you generated again, unless you went crazy and wrote a webhook to go in and regenerate it...) you get the picture, it's a rabbit hole!
Nov 21, 2021, 9:12 PM
Yeah it does sound like it's gonna cause a lot of issues. I'm just trying to get my mind into the process the client (as in the actual client, not the
document) is gonna be expecting... I feel like they're gonna want to create a
and then within that create `Project`'s, but I know Sanity doesn't necessarily work like that.
Wondering if I need to create an array of `Project`'s inside
documents or something
Nov 21, 2021, 9:15 PM
Yup - you are running into the thing many have run into. You can't -- at the moment -- create a document in place as a reference.
Nov 21, 2021, 9:16 PM
I'm sure it's something sanity will address at some point. I get the logic of separating everything for re-use, but sometimes it makes a lot of sense that things be nested like that
Nov 21, 2021, 9:17 PM
You could, have each
be an object and then create them in place, but then your projects would be forever coupled with their
Nov 21, 2021, 9:19 PM
I think creating an
within a
page might work here. I could do away with the slug I guess. It's mainly so the client has some way of linking particular pages to their own clients
Nov 21, 2021, 9:19 PM
Well, I used projects as an example, but actually they're decks, like slideshows or keynotes, so them being forever associated with a client is okay. Although I can see times when they might want to duplicate a deck from one client to another...
Nov 21, 2021, 9:20 PM
Yeah, my gut says to keep them as documents. They are much more queryable, manageable and relatable that way. The hard part is training the sanity users to create the decks "on their own" and then go back to the client document and add the references to now-existing decks in there. I believe there is a plan to add the create-referenced-doc-in-place feature though, here's the github issue: https://github.com/sanity-io/sanity/issues/507
Nov 21, 2021, 9:26 PM
^I have a project where I convinced myself I could leave something as an embedded object, but I regretted it because unexpectedly the Sanity users now wanted to be able to bulk add hundreds of them and I have a janky-hard-to-remember-what-I-did way to update them now.
Nov 21, 2021, 9:27 PM
Yeah I think you're absolutely right. I'm just thinking as well, by doing it this way (keeping the decks as separate documents, and then referencing them in the client area), you could potentially reference the same deck in multiple client areas if they had something "generic"
Nov 21, 2021, 9:31 PM
Could even do some magic with the decks themselves where you insert the client name into it based on the reference. For example, "Dear <client_name>" and replace it with the
Nov 21, 2021, 9:32 PM
Just thinking outloud but you've really helped me nail down the direction for this
user U
— thank you!
Nov 21, 2021, 9:33 PM
Hi - no prob! It also helps me to think this sort of thing through, and yup, if they are separate then you'll have that flexibility, and also a way to query decks across clients if that ever becomes a thing.
Nov 21, 2021, 10:56 PM
Great discussion here guys! If your
is a document with a
in a reference field, you could generate a unique slug only among the projects from the same client by:
• use the client _id as the source of the slug
• in a custom slugify, fetch all the slug from the same client id & check unique against that
Nov 22, 2021, 6: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?