Discussion on how to structure clients and projects in Sanity, including unique slugs and references.
18 replies
Last updated: Nov 22, 2021
C
Morning everyone 🙂
If I wanted to create a structure like this, how would I best do it?
ie.
The question mark for me is I don't want one
ie.
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
Clientswould include a unique slug for the client name, and
Projectswould be nested under
Clients, again with a unique slug.
The question mark for me is I don't want one
Clientto include projects with the same slug, as the URL would look like
client-one/code-veronicaso would need to be unique. However, another
Clientcould include a matching slug, as it would still be unique in this case.
ie.
client-one/project-x- Valid
client-one/project-x- Invalid (matches previous)
client-two/project-x- Valid
Nov 21, 2021, 10:00 AM
C
It's the slugs thing I'm stuck with 🙂
Nov 21, 2021, 10:01 AM
C
One thought would be to a custom
slugifyfunction with
isUniqueto add the client name to the slug, but at the moment I don't know how to directly nest
Projectsbeneath
Clientsso 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:
•
https://www.sanity.io/docs/slug-type#d5066a58b95a
Beyond that, if you wanted to make your
•
Clientand
Projectexist as documents • Each uses the default
isUniqueoption to maintain the uniqueness of their slug among documents of their type. •
Clienthas a field called
Projectsthat is an array of references to existing projects. • Your front end will have the task of building urls like
/client-one/project-xand 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
Clientdocument can reference any number of
Projectdocuments. 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:
https://www.sanity.io/docs/slug-type#d5066a58b95a
Beyond that, if you wanted to make your
Projectslugs contain data from
Clientsthat 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
C
Hey
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? example-client/project-xand
another-example/project-x— with your approach, I don't think this would be possible as it would have to be
another-example/project-x-2
Nov 21, 2021, 5:47 PM
Hi - so, by design the
...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
slugfield is required to be unique among documents of its type. If you wanted to make sure that information about the referencing
Clientwas automatically included in the slug of a
Projectyou could put this function in the
sourceoption 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}` }) }
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
titlethe 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
C
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
Wondering if I need to create an array of `Project`'s inside
Clientdocument) is gonna be expecting... I feel like they're gonna want to create a
Clientand 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
Clientdocuments 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
C
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
projectbe an object and then create them in place, but then your projects would be forever coupled with their
Clients.
Nov 21, 2021, 9:19 PM
C
I think creating an
arraywithin a
Clientpage 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
C
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
C
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
C
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
Clienttitle
Nov 21, 2021, 9:32 PM
C
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
D
Great discussion here guys! If your
• 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
projectis a document with a
clientin 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.