Transcript
Hey, how's it going? So I want to do this very quick video because a lot of people have been asking me how to get the most out of Turbo, and I want to basically get right into it, talk about how we actually build websites and our development flow, and show you all the different ways that you can actually use this. But from the very start, I want to talk about how this is actually structured, why it's structured that way, and just go through a few things.
So first of all, you'll notice that we have this apps. This apps is because it's a monorepo, and you can see that we have a pnpm file. And if you press command P and you go look for some packages, you'll notice there's a hell of a lot of different packages in here. There is this main one that basically sits at the very top level. Very easy pitfall to do, but don't do this: installing things on the root. You don't want to do this because you don't need to have many packages in the root's package.json. You can see that they have very, very few inside of here. And the same—so when it comes to actually building the user interface of this and using things from things like Shad CN UI, which I definitely recommend using, they're going to go into the packages UI package.json. That's where it goes in. So you can see already we have Radix, React accordions, and all this kind of good stuff.
And now with that being said, the majority of stuff you're probably going to install that's not related to Shad CN is going to be in package.json in the web folder. However, something that's kind of interesting about this: if you try installing Shad CN in the web folder, it'll automatically get extracted out into the UI part of the website, which is kind of cool. You have environmental examples inside of here, an environment file that gets generated when you first spin this up. But right now we're going to make sure we get started. So let's run prd. This is just the post install. So I'm using pnpm run. Make sure you're using pnpm. Let me get rid of that. Let's do that again.
So you should 100% use pnpm rather than npm because it's going to save you a whole bunch of data when you're actually using these tools, because we install a hell of a lot, you know, Next and Sanity in hundreds of projects. So yeah, here we go. Here's the first thing you'll probably see. And you can have this in dark mode, you can have this in light mode, all of this good stuff, or system. This is all just data that's taken from Faker and populated inside of here. So you can tweak all of this and change it however you want.
But realistically, what you want to be doing is building your first page builder block. Now today I'm only going to really focus on the page builder block side of things because that's kind of the most important. But ultimately we have this thing called page builder. You'll notice there's two files. One of them is the definitions inside of schema types. Always pay attention to this thing. You see where it says studio? So studio here, web here. The web and the general rule of thumb—although this is not always the perfect way of looking at it—most of the time .ts is going to be inside of the studio, so the Sanity Studio, and then the other times .tsx is going to be in the actual web side of the website, so the Next.js environment.
I'll give you an example here. So let's go to page builder. Let's see how this is actually built. Okay, cool. So this is essentially an array. It's going through the array and it's mapping each block to each member inside of that. So let's hit page builder blocks and see how that works. Cool, this is how we handle our page builder blocks and how we essentially assert them. So let's go click one of these. Let's go see hero, and here is a hero block.
Now one thing that we are going to do to improve Turbo start in the future is putting in some rules. I actually would recommend putting in these rules inside of Cursor—sorry, not Sanity, inside of Cursor. So you can see if you go into, I believe it's rules inside of here, you can start creating project rules. We are going to include some project rules at a later date. But if you are trying to use as much as you can from today outside of Cursor, that's the way you do it.
With that being said, let's then move on to creating our first schema. And you can do a lot of the schema generation with AI, but I would highly recommend going through the Sanity learn. But for the time being, we're going to go for a brand new schema called example block. And all this is going to be is an image, a title, and a rich text, and I'll show you how that works.
So there is an extension that's quite useful called Sanity Snippets, I think. It just essentially allows you to put a Sanity schema in. So if I go—I've forgot the exact way that you do this now—essentially I'm going to go take it from another one because it's been too long since I've done this manually. These days I'm actually using AI a lot to be able to generate this stuff, which is pretty poor, but bear with me.
Example block. Let's put this in. So let's go create a schema that uses a title—because we always use titles as a title, if you keep standardizing the fields, always keep that in the back of your mind—rich text and an image, and we're going to hit enter. And this is going to generate the example block. I am using Claude 3.5 thinking. It's good, basically as good as the regular one. I just thought I'd see if it gets it right first time on this. And I'm using the agent. You can do this with command K as well, but this is just a nice, quick, easy way to do it.
And for most people that are watching this, I'm guessing a lot of developers these days are just actually blasting these things out with AI. I cannot tell you how important it is to not make a fool of yourself like myself where you try actually writing one of these things out manually and forgetting how you do it. So we'll see this. So create a new schema that uses this. So first mistake, and this is actually very helpful to use: instead of calling it example block, it's created a brand new block called content with image. So something to be aware of that AI does very often is it generates a hell of a lot of code, but it's very poor at removing that code. You can also see—so I'll get rid of this example block and we'll stick with what it's created, which is this content with image. You'll notice that we have this defined field. This is just Sanity and this is TypeScript, which is really helpful.
Something to know about the project as well: the whole project generates types for you. So as soon as we have included this within the index—and we will, we will also—let's see where this is getting pulled into. Yep, this is correct. So this is inside of the index. Let me double check that it's inside of the page builder. It will be, because that's where the blocks are coming from. So this is wonderful.
Now the next thing we want to do is we want to run pnpm run type. So pnpm run type. And what this will do is—you will forget that it's not actually included—you can actually set this up so you can do it from the root directory, but I haven't inside of Turbo, so we will make sure that we get that soon. Again, I'm making sure that we hit all of these errors intentionally to try and provide some education with all of this, because it actually is worth knowing. And you can see that we had 45 schemas created, 45 schema types, and 13 GraphQL queries.
So if I flip back very quickly, you will now notice that if I go ahead and I build an equivalent block—so content with image—I'm going to go ahead and find another block that exists on this. So hero.tsx. You'll notice that they are always named the same thing: hero.tsx, hero.ts. So let's go here, and you'll notice it's in the sections. And what we're going to do, we're going to do a brand new file and we're going to call it the same as what we have: content with image.tsx.
Okay, now what we can do is we can go back to here, we can pop this in, and we can say: let's get content with image, let's pull both versions. So that version, this version, get rid of example block because we don't need it anymore. And say: I would like to create a basic block with content with image schema, can you use—and again, we can use other ones. So like one of the things that I would always recommend is very helpful is using another component to opinionated what this one's going to do. So can you use at hero.tsx to see how we handle images and rich text, etc.? So going to hit enter again, and you'll see this should hopefully populate this content with image. The one thing that might be interesting is whether it gets the type correct or not, because it's generated that type. But also the type generation file is absolutely massive. It looks like it did it correctly. Yep. You'll see that we now have this.
Now the thing is, we don't have this left right. So can you see we have this image position? But unless it did include that on the—do we have a left right in here? Oh, we do have a left right. Okay, cool, so that's fine. Let's see what it's complaining about here. Ah, this image asset. That's interesting. Let's see what it does. I'm really curious as to whether it will fix it or not. So we can have a quick look on here as to how the Sanity hero image asset worked. So image—let's have a quick look. Hero page builder type hero. Let's see. Let's move back and see what's going on. Asset image. Where's the problem here? Property asset, which is declared on... okay, so let's go check this out. Let's go check what this might be getting caused by. I have a feeling this is to do with the query. So let's go check the queries out. And you'll notice there is an image fragment on here. Let's see if there's one for... let's stop this. Okay, we'll accept what it's got so far. That's fine. And we will look at the hero block.
So if we go to hero block inside of here, I notice that there is an image fragment and a rich text fragment. Now this is the way that we handle GraphQL. So if we go one below, we were going to say content with image block. Let's take that for now. And we want that—that's actually exactly what we want. So let's just finish that one off. Perfect. And then let's take this content with image block and pop that into the page builder, wherever that is. Is it down here? Yep, perfect.
Now if we pop back and we run this again—so let's run the pnpm run type—see if it breaks, and we'll go through if it breaks as well, because that'll be really helpful. This just means that everything that you're writing up is actually fully TypeScript. And you'll see: bada bing, bada boom, it just went green, which is great news. So that's worked, and it was all down to a couple different files: the query file with Sanity and making sure we're using these fragments.
The reason why these fragments are so useful is that at first it seems like a lot of fuss and a lot of hassle, but as the website scales and you have like 600, 700 pages, this is not a lot of hassle. What is a lot of hassle is trying to figure out why your queries are timing out because you're pulling so much data in one go. So I definitely recommend doing this. And as you can see, this is now all wired up.
Let's go on to Arc and let's go into localhost 3333, which is the Sanity environment. And inside of here we should give it a couple seconds. Oh, here we go. Let's log in. I'm really hoping it doesn't come up with an error. Okay, cool. So let's go to structure. Let's go to pages. We can do this through the actual presentation, but for example, let's take this page and let's hit the plus. What is this? Get rid of that. And let's do content with image. So this was it. So we know that if this works, this is actually working. So write "content with image". Content with image title, rich text. Let's choose an image from whatever's in the environment. Oh, that one's not so good. Let's pick one from Unsplash. Let's go for this nice coffee-looking thing. Let's wait for that to download, and then we're going to hit publish. And this should be lovely. A little bit of rich text to complement the block. Okay, hit publish. Ignore the low battery. Okay, and what we're going to do, we're going to hit—we can open this. So we can actually go back, pages, go into here, and open it this way. Opening presentation should open straight away, and we'll see if it's in there.
Ooh, component not found with block type content with image. Now let's find out how we fix that. So remember how we had this page builder here? The problem is that we have another page builder here that we forgot to put it in. So if we pop down a level, you'll see that we have content image with block—or content with image block. And now we've added those two. So again, it's just literally the actual string and then this version that is the actual component itself. So in theory that should have just worked, and we'll see if it has. And there you go. That is a full Sanity block being built for a page builder from start to finish. It took us less than 15 minutes, which is great. But this is a very, very simple version. As your website scales, this will scale with it, and this will be very, very good for building these kind of websites. But this is the baseline for building these blocks and what you can essentially do with the project.
Yeah, have a great day. Take care. Bye-bye.