About this video
Rough cut process of building page builder blocks within Turbo Start Sanity. Watch the schema, queries, and components come together in real time.
Full transcript
Edited transcript from the original Roboto page
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 applies here. 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 here: 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: 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. 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 did it include that? 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 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.
Read timestamped source captions
0:04hey how's it going so I want to do this
0:04hey how's it going so I want to do this very quick video because a lot of people
0:05very quick video because a lot of people
0:05very quick video because a lot of people have been asking me how to get the most
0:08have been asking me how to get the most
0:08have been asking me how to get the most out of Turbo and I want to get I want to
0:11out of Turbo and I want to get I want to
0:11out of Turbo and I want to get I want to basically get right into it talk about
0:12basically get right into it talk about
0:12basically get right into it talk about how we actually build websites and our
0:14how we actually build websites and our
0:14how we actually build websites and our development flow and show you all the
0:16development flow and show you all the
0:16development flow and show you all the different ways that you can actually use
0:17different ways that you can actually use
0:17different ways that you can actually use this um but from the very start I want
0:19this um but from the very start I want
0:19this um but from the very start I want to talk about how this is actually
0:21to talk about how this is actually
0:21to talk about how this is actually structured why it's structured that way
0:23structured why it's structured that way
0:23structured why it's structured that way and just go through a little few things
0:24and just go through a little few things
0:25and just go through a little few things so first of all you'll notice that we
0:26so first of all you'll notice that we
0:26so first of all you'll notice that we have this apps um this apps is because
0:28have this apps um this apps is because
0:28have this apps um this apps is because it's a mono repo and you can see that we
0:30it's a mono repo and you can see that we
0:30it's a mono repo and you can see that we have a pmpm file and if you press
0:32have a pmpm file and if you press
0:32have a pmpm file and if you press command p and you go look for some
0:33command p and you go look for some
0:33command p and you go look for some packages you'll notice there's a hell of
0:35packages you'll notice there's a hell of
0:35packages you'll notice there's a hell of a lot of different packages in here
0:37a lot of different packages in here
0:37a lot of different packages in here there is this main one that basically
0:38there is this main one that basically
0:38there is this main one that basically sits at the very top level uh very easy
0:40sits at the very top level uh very easy
0:41sits at the very top level uh very easy pitf to do but don't do this is
0:43pitf to do but don't do this is
0:43pitf to do but don't do this is installing things on the route um you
0:46installing things on the route um you
0:46installing things on the route um you don't want to do this because you don't
0:47don't want to do this because you don't
0:47don't want to do this because you don't need to have many packages in The Roots
0:49need to have many packages in The Roots
0:49need to have many packages in The Roots package.json you can see that they have
0:51package.json you can see that they have
0:51package.json you can see that they have very very few inside of here um and the
0:54very very few inside of here um and the
0:54very very few inside of here um and the same uh so when it comes to actually
0:57same uh so when it comes to actually
0:57same uh so when it comes to actually building the user interface of this and
0:58building the user interface of this and
0:58building the user interface of this and using things from things like Shad CN UI
1:01using things from things like Shad CN UI
1:01using things from things like Shad CN UI which I definitely recommend using
1:03which I definitely recommend using
1:03which I definitely recommend using they're going to go into the packages UI
1:05they're going to go into the packages UI
1:05they're going to go into the packages UI package.json that's where it goes into
1:07package.json that's where it goes into
1:07package.json that's where it goes into so you can see already we have radx
1:09so you can see already we have radx
1:09so you can see already we have radx react accordians and all this kind of
1:11react accordians and all this kind of
1:11react accordians and all this kind of good stuff um and now with that being
1:14good stuff um and now with that being
1:14good stuff um and now with that being said uh the majority of stuff you're
1:17said uh the majority of stuff you're
1:17said uh the majority of stuff you're probably going to install uh that's not
1:19probably going to install uh that's not
1:19probably going to install uh that's not related to Shaden is going to be in
1:21related to Shaden is going to be in
1:21related to Shaden is going to be in package doj uh. Json in the web folder
1:24package doj uh. Json in the web folder
1:24package doj uh. Json in the web folder however something that's kind of
1:25however something that's kind of
1:25however something that's kind of interesting about this if you try
1:26interesting about this if you try
1:26interesting about this if you try installing Shaden in the web folder
1:28installing Shaden in the web folder
1:28installing Shaden in the web folder it'll automatically get extracted out
1:30it'll automatically get extracted out
1:30it'll automatically get extracted out into the UI uh part of the website which
1:34into the UI uh part of the website which
1:34into the UI uh part of the website which is kind of
1:35is kind of
1:35is kind of cool um you have environmental examples
1:38cool um you have environmental examples
1:38cool um you have environmental examples inside of here an environmental dolal
1:40inside of here an environmental dolal
1:40inside of here an environmental dolal that gets generated when you first spin
1:41that gets generated when you first spin
1:41that gets generated when you first spin this up um but right now we're going to
1:43this up um but right now we're going to
1:43this up um but right now we're going to make sure we get started so let's run uh
1:46make sure we get started so let's run uh
1:46make sure we get started so let's run uh PRD this is just the post install so I'm
1:49PRD this is just the post install so I'm
1:49PRD this is just the post install so I'm using pmpm runev make sure you're using
1:52using pmpm runev make sure you're using
1:52using pmpm runev make sure you're using pmpm um let me get rid of that let's do
1:55pmpm um let me get rid of that let's do
1:55pmpm um let me get rid of that let's do that again um so you should 100% use
1:57that again um so you should 100% use
1:58that again um so you should 100% use pmpm rather than mpm because it's going
2:00pmpm rather than mpm because it's going
2:00pmpm rather than mpm because it's going to save you a whole bunch of uh data
2:02to save you a whole bunch of uh data
2:02to save you a whole bunch of uh data when you're actually using um these
2:04when you're actually using um these
2:04when you're actually using um these tools cuz we install a hell of a lot of
2:06tools cuz we install a hell of a lot of
2:06tools cuz we install a hell of a lot of you know next sanity in hundreds of
2:09you know next sanity in hundreds of
2:09you know next sanity in hundreds of projects um so yeah here we go here's
2:11projects um so yeah here we go here's
2:11projects um so yeah here we go here's the first thing you'll probably see um
2:13the first thing you'll probably see um
2:13the first thing you'll probably see um and you can have this in dark mode you
2:14and you can have this in dark mode you
2:14and you can have this in dark mode you can have this in light mode all of this
2:16can have this in light mode all of this
2:16can have this in light mode all of this good stuff uh or system um this is all
2:19good stuff uh or system um this is all
2:19good stuff uh or system um this is all just data that's taken from Faker and
2:21just data that's taken from Faker and
2:21just data that's taken from Faker and populated inside of here so you can
2:23populated inside of here so you can
2:23populated inside of here so you can tweak all of this and change it however
2:25tweak all of this and change it however
2:25tweak all of this and change it however you want um but realistically what you
2:27you want um but realistically what you
2:27you want um but realistically what you want to be doing is building your first
2:29want to be doing is building your first
2:29want to be doing is building your first page builder block now today I'm only
2:31page builder block now today I'm only
2:31page builder block now today I'm only going to really focus on the page
2:32going to really focus on the page
2:32going to really focus on the page builder block side of things because
2:34builder block side of things because
2:34builder block side of things because that's kind of the most important um but
2:37that's kind of the most important um but
2:37that's kind of the most important um but ultimately we have this thing called
2:39ultimately we have this thing called
2:39ultimately we have this thing called page builder uh you'll notice there's
2:41page builder uh you'll notice there's
2:41page builder uh you'll notice there's two files one of them is the definitions
2:43two files one of them is the definitions
2:43two files one of them is the definitions inside of schema types uh always pay
2:45inside of schema types uh always pay
2:45inside of schema types uh always pay attention to this thing you see where it
2:46attention to this thing you see where it
2:46attention to this thing you see where it says studio so Studio here web here um
2:50says studio so Studio here web here um
2:50says studio so Studio here web here um the web and the the general rule of
2:51the web and the the general rule of
2:52the web and the the general rule of thumb although this is not always the
2:53thumb although this is not always the
2:53thumb although this is not always the perfect way of looking at it most of the
2:55perfect way of looking at it most of the
2:55perfect way of looking at it most of the time it's going to be TS is going to be
2:57time it's going to be TS is going to be
2:57time it's going to be TS is going to be inside of the studio so the sanity
2:58inside of the studio so the sanity
2:58inside of the studio so the sanity studio and then the other times. TSX is
3:01studio and then the other times. TSX is
3:01studio and then the other times. TSX is going to be in the actual webside of the
3:03going to be in the actual webside of the
3:03going to be in the actual webside of the website so the nextjs environment I'll
3:06website so the nextjs environment I'll
3:06website so the nextjs environment I'll give you an example here so let's go to
3:07give you an example here so let's go to
3:07give you an example here so let's go to page builder um let's see how this is
3:09page builder um let's see how this is
3:09page builder um let's see how this is actually built Okay cool so this is
3:12actually built Okay cool so this is
3:12actually built Okay cool so this is essentially array it's going through the
3:14essentially array it's going through the
3:14essentially array it's going through the uh array and it's mapping each block to
3:17uh array and it's mapping each block to
3:17uh array and it's mapping each block to each member inside of that so let's hit
3:18each member inside of that so let's hit
3:19each member inside of that so let's hit page builder blocks and see how that
3:20page builder blocks and see how that
3:20page builder blocks and see how that works cool this is how we handle our
3:23works cool this is how we handle our
3:23works cool this is how we handle our page builder blocks and how we
3:24page builder blocks and how we
3:24page builder blocks and how we essentially assort them so let's go
3:26essentially assort them so let's go
3:26essentially assort them so let's go click one of these let's go see hero and
3:28click one of these let's go see hero and
3:28click one of these let's go see hero and here is a hero block now one thing that
3:30here is a hero block now one thing that
3:31here is a hero block now one thing that we are going to do to improve turbo
3:32we are going to do to improve turbo
3:32we are going to do to improve turbo start in the future is putting in some
3:34start in the future is putting in some
3:34start in the future is putting in some rules um I actually would recommend
3:36rules um I actually would recommend
3:36rules um I actually would recommend putting in these rules inside of Sanity
3:39putting in these rules inside of Sanity
3:39putting in these rules inside of Sanity um inside of cursor sorry not sanity um
3:41um inside of cursor sorry not sanity um
3:42um inside of cursor sorry not sanity um so you can see if you go into I believe
3:43so you can see if you go into I believe
3:43so you can see if you go into I believe it's rules inside of here you can start
3:45it's rules inside of here you can start
3:45it's rules inside of here you can start creating project rules uh we are going
3:47creating project rules uh we are going
3:47creating project rules uh we are going to include some project rules at a later
3:49to include some project rules at a later
3:49to include some project rules at a later date um but if you are trying to use as
3:51date um but if you are trying to use as
3:51date um but if you are trying to use as much as you can from today outside of
3:53much as you can from today outside of
3:53much as you can from today outside of cursor that's the way you do it um with
3:56cursor that's the way you do it um with
3:56cursor that's the way you do it um with that being said uh let's then move on to
3:59that being said uh let's then move on to
3:59that being said uh let's then move on to creating our first schema um and you can
4:01creating our first schema um and you can
4:01creating our first schema um and you can do a lot of the schema generation with
4:04do a lot of the schema generation with
4:04do a lot of the schema generation with AI but I would highly recommend going
4:05AI but I would highly recommend going
4:06AI but I would highly recommend going through the sanity learn um but for the
4:08through the sanity learn um but for the
4:08through the sanity learn um but for the time being we're going to go for a brand
4:09time being we're going to go for a brand
4:09time being we're going to go for a brand new schema called uh example uh example
4:13new schema called uh example uh example
4:13new schema called uh example uh example block um and all this is going to be is
4:17block um and all this is going to be is
4:17block um and all this is going to be is a image a title and a rich text and I'll
4:20a image a title and a rich text and I'll
4:20a image a title and a rich text and I'll show you how that works so there is an
4:22show you how that works so there is an
4:22show you how that works so there is an extension that's quite useful uh called
4:25extension that's quite useful uh called
4:25extension that's quite useful uh called sanity what is it sanity Snippets I
4:29sanity what is it sanity Snippets I
4:29sanity what is it sanity Snippets I think I think it's this one um where it
4:31think I think it's this one um where it
4:31think I think it's this one um where it just essentially allows you to put a
4:33just essentially allows you to put a
4:33just essentially allows you to put a sanity schemer in so if I go
4:36sanity schemer in so if I go
4:36sanity schemer in so if I go uh I've forgot the exact way that you do
4:38uh I've forgot the exact way that you do
4:38uh I've forgot the exact way that you do this now um essentially I'm going to go
4:40this now um essentially I'm going to go
4:40this now um essentially I'm going to go take it from another one because it's
4:42take it from another one because it's
4:42take it from another one because it's been too long since I've done this
4:44been too long since I've done this
4:44been too long since I've done this manually um these days I'm actually
4:47manually um these days I'm actually
4:47manually um these days I'm actually using um AI a lot to be able to generate
4:50using um AI a lot to be able to generate
4:50using um AI a lot to be able to generate this stuff which is pretty poor but bear
4:53this stuff which is pretty poor but bear
4:53this stuff which is pretty poor but bear with me so example block um let's put
4:55with me so example block um let's put
4:55with me so example block um let's put this in so let's go uh create a schema
4:59this in so let's go uh create a schema
4:59this in so let's go uh create a schema that uses um title because we always use
5:03that uses um title because we always use
5:03that uses um title because we always use titles as a title if you keep
5:05titles as a title if you keep
5:05titles as a title if you keep standardizing the fields always keep
5:06standardizing the fields always keep
5:06standardizing the fields always keep that in the back of your mind um Rich
5:10that in the back of your mind um Rich
5:10that in the back of your mind um Rich text and an
5:13text and an
5:13text and an image and we're going to hit enter and
5:15image and we're going to hit enter and
5:15image and we're going to hit enter and this is going to check check the example
5:16this is going to check check the example
5:16this is going to check check the example block I am using the um what is it
5:19block I am using the um what is it
5:19block I am using the um what is it called Claude 3.7 thinking Max um and
5:25called Claude 3.7 thinking Max um and
5:25called Claude 3.7 thinking Max um and it's it's good it's good as basically
5:29it's it's good it's good as basically
5:29it's it's good it's good as basically the regular one um I just thought I'd
5:31the regular one um I just thought I'd
5:31the regular one um I just thought I'd see if it gets it right first time on
5:32see if it gets it right first time on
5:32see if it gets it right first time on this um and I am using the agent you can
5:36this um and I am using the agent you can
5:36this um and I am using the agent you can do this with command K as well um but
5:38do this with command K as well um but
5:38do this with command K as well um but this is just a nice quick easy way to do
5:39this is just a nice quick easy way to do
5:40this is just a nice quick easy way to do it um and for most people that are
5:41it um and for most people that are
5:41it um and for most people that are watching this I'm guessing a lot of
5:43watching this I'm guessing a lot of
5:43watching this I'm guessing a lot of developers these days are just actually
5:44developers these days are just actually
5:44developers these days are just actually blasting these things out with AI I
5:46blasting these things out with AI I
5:46blasting these things out with AI I cannot tell you how important it is to
5:48cannot tell you how important it is to
5:48cannot tell you how important it is to not make a fool of yourself like myself
5:50not make a fool of yourself like myself
5:50not make a fool of yourself like myself where you try actually writing one of
5:51where you try actually writing one of
5:51where you try actually writing one of these things out manually and forgetting
5:53these things out manually and forgetting
5:53these things out manually and forgetting how you do it um so we'll see this so
5:57how you do it um so we'll see this so
5:57how you do it um so we'll see this so create a new schema that uses this
6:00create a new schema that uses this
6:00create a new schema that uses this so first first mistake and this is
6:03so first first mistake and this is
6:03so first first mistake and this is actually very helpful to to use so
6:05actually very helpful to to use so
6:05actually very helpful to to use so instead of calling instead of using the
6:06instead of calling instead of using the
6:07instead of calling instead of using the example block um it's created a brand
6:09example block um it's created a brand
6:09example block um it's created a brand new block called content with image so
6:11new block called content with image so
6:11new block called content with image so something to be aware of that AI does
6:12something to be aware of that AI does
6:12something to be aware of that AI does very often is it generates a hell of a
6:15very often is it generates a hell of a
6:15very often is it generates a hell of a lot of um code but it's very poor at
6:18lot of um code but it's very poor at
6:18lot of um code but it's very poor at removing that code um you can also see
6:21removing that code um you can also see
6:21removing that code um you can also see so I'll get rid of this example block
6:22so I'll get rid of this example block
6:22so I'll get rid of this example block and we'll stick with what we've what
6:24and we'll stick with what we've what
6:24and we'll stick with what we've what it's created which is this content with
6:25it's created which is this content with
6:26it's created which is this content with image um you'll notice that we have this
6:28image um you'll notice that we have this
6:28image um you'll notice that we have this defined field defined timee this is just
6:30defined field defined timee this is just
6:30defined field defined timee this is just sanity and this is typescripts which is
6:31sanity and this is typescripts which is
6:32sanity and this is typescripts which is really helpful um something to know
6:33really helpful um something to know
6:33really helpful um something to know about the project as well the whole
6:35about the project as well the whole
6:35about the project as well the whole project generates types for you so as
6:38project generates types for you so as
6:38project generates types for you so as soon as we have included this within the
6:40soon as we have included this within the
6:40soon as we have included this within the index um and we will we will also let's
6:43index um and we will we will also let's
6:43index um and we will we will also let's see where this is getting pulled into
6:45see where this is getting pulled into
6:45see where this is getting pulled into Yep this is correct so this is inside of
6:47Yep this is correct so this is inside of
6:47Yep this is correct so this is inside of the index um let me double check that
6:49the index um let me double check that
6:49the index um let me double check that it's inside of the page builder it will
6:51it's inside of the page builder it will
6:51it's inside of the page builder it will be because uh that's where the blocks
6:53be because uh that's where the blocks
6:53be because uh that's where the blocks are coming from so this is wonderful now
6:56are coming from so this is wonderful now
6:56are coming from so this is wonderful now the next thing we want to do is we want
6:58the next thing we want to do is we want
6:58the next thing we want to do is we want to run mpm run type um so PN PM PM I use
7:03to run mpm run type um so PN PM PM I use
7:03to run mpm run type um so PN PM PM I use PN as a a little tiny version so PN run
7:09PN as a a little tiny version so PN run
7:09PN as a a little tiny version so PN run type and what this will do is you will
7:14type and what this will do is you will
7:14type and what this will do is you will forget that it's not actually included
7:16forget that it's not actually included
7:16forget that it's not actually included on you can actually set this up so you
7:18on you can actually set this up so you
7:18on you can actually set this up so you can do it from the root directory but I
7:20can do it from the root directory but I
7:20can do it from the root directory but I haven't inside of Turbo so we will make
7:22haven't inside of Turbo so we will make
7:22haven't inside of Turbo so we will make sure that we get that soon um again I'm
7:24sure that we get that soon um again I'm
7:24sure that we get that soon um again I'm making sure that we hit all of these
7:25making sure that we hit all of these
7:25making sure that we hit all of these errors intentionally um to try and
7:28errors intentionally um to try and
7:28errors intentionally um to try and provide some education with all of this
7:30provide some education with all of this
7:30provide some education with all of this um because it actually is worth knowing
7:32um because it actually is worth knowing
7:32um because it actually is worth knowing and you can see that we had 45 schemers
7:34and you can see that we had 45 schemers
7:35and you can see that we had 45 schemers created 45 schemers types and 13 grck
7:37created 45 schemers types and 13 grck
7:37created 45 schemers types and 13 grck queries um so if I flip back very
7:40queries um so if I flip back very
7:40queries um so if I flip back very quickly um you will now notice that if I
7:43quickly um you will now notice that if I
7:43quickly um you will now notice that if I go ahead and I build an equivalent block
7:46go ahead and I build an equivalent block
7:46go ahead and I build an equivalent block so content with image um I'm going to go
7:48so content with image um I'm going to go
7:48so content with image um I'm going to go ahead and find uh another block that
7:50ahead and find uh another block that
7:50ahead and find uh another block that exists on this so hero. TSX you'll
7:52exists on this so hero. TSX you'll
7:52exists on this so hero. TSX you'll notice that they are always named the
7:55notice that they are always named the
7:55notice that they are always named the same thing so hero. TSX hero. TS um so
7:59same thing so hero. TSX hero. TS um so
7:59same thing so hero. TSX hero. TS um so let's go here and you'll notice it's in
8:01let's go here and you'll notice it's in
8:01let's go here and you'll notice it's in the sections um and what we're going to
8:03the sections um and what we're going to
8:03the sections um and what we're going to do we're going to do a brand new file
8:04do we're going to do a brand new file
8:04do we're going to do a brand new file and we're going to call it the same as
8:05and we're going to call it the same as
8:05and we're going to call it the same as what we have so content with image. TSX
8:10what we have so content with image. TSX
8:11what we have so content with image. TSX okay now um what we can do is is we can
8:13okay now um what we can do is is we can
8:13okay now um what we can do is is we can go back to here we can pop this in and
8:15go back to here we can pop this in and
8:15go back to here we can pop this in and we can say um uh let's get content with
8:19we can say um uh let's get content with
8:19we can say um uh let's get content with image let's pull both versions so that
8:21image let's pull both versions so that
8:21image let's pull both versions so that version this version get rid of example
8:23version this version get rid of example
8:23version this version get rid of example block cuz we don't need it anymore and
8:25block cuz we don't need it anymore and
8:25block cuz we don't need it anymore and say I would like to create a b basic
8:30say I would like to create a b basic
8:30say I would like to create a b basic block with um content with
8:35block with um content with
8:35block with um content with image schema can you use and again we
8:39image schema can you use and again we
8:39image schema can you use and again we can use other ones so like one of the
8:41can use other ones so like one of the
8:41can use other ones so like one of the things that I would always recommend is
8:42things that I would always recommend is
8:43things that I would always recommend is very helpful is using another component
8:46very helpful is using another component
8:46very helpful is using another component to opinionate what this one's going to
8:48to opinionate what this one's going to
8:48to opinionate what this one's going to do so uh can you use at
8:51do so uh can you use at
8:51do so uh can you use at hero. TSX to see how we handle images
8:57hero. TSX to see how we handle images
8:57hero. TSX to see how we handle images and Rich Text Etc
9:00and Rich Text Etc
9:00and Rich Text Etc um so going to hit enter again and
9:02um so going to hit enter again and
9:02um so going to hit enter again and you'll see this should hopefully
9:03you'll see this should hopefully
9:03you'll see this should hopefully populate this content with image the one
9:06populate this content with image the one
9:06populate this content with image the one thing that might be interesting is
9:08thing that might be interesting is
9:08thing that might be interesting is whether it gets the type correct or not
9:10whether it gets the type correct or not
9:10whether it gets the type correct or not um because it's generated that type but
9:12um because it's generated that type but
9:12um because it's generated that type but also the type generation file is
9:14also the type generation file is
9:14also the type generation file is absolutely massive it looks like it did
9:16absolutely massive it looks like it did
9:16absolutely massive it looks like it did it correctly yep um you'll see that we
9:19it correctly yep um you'll see that we
9:19it correctly yep um you'll see that we now have this now the thing is is we
9:21now have this now the thing is is we
9:21now have this now the thing is is we don't have this left right so can you
9:22don't have this left right so can you
9:22don't have this left right so can you see we have this image position but I
9:24see we have this image position but I
9:24see we have this image position but I unless it did include that on the do we
9:28unless it did include that on the do we
9:28unless it did include that on the do we have a left right in here oh we do have
9:30have a left right in here oh we do have
9:30have a left right in here oh we do have a left right okay cool so that's fine
9:33a left right okay cool so that's fine
9:33a left right okay cool so that's fine let's see what it's it's uh complaining
9:35let's see what it's it's uh complaining
9:35let's see what it's it's uh complaining about here ah this image asset that's
9:39about here ah this image asset that's
9:39about here ah this image asset that's interesting let's see what it does I'm
9:42interesting let's see what it does I'm
9:42interesting let's see what it does I'm really curious as to whether it will fix
9:43really curious as to whether it will fix
9:43really curious as to whether it will fix it or
9:45it or
9:45it or not so we can have a quick look on here
9:48not so we can have a quick look on here
9:48not so we can have a quick look on here as to how the sanity hero image asset
9:51as to how the sanity hero image asset
9:51as to how the sanity hero image asset worked so image let's have a quick look
9:55worked so image let's have a quick look
9:55worked so image let's have a quick look hero page builder type hero
10:03let's see let's move back and see what's
10:03let's see let's move back and see what's going
10:09on asset image where's the problem here
10:10on asset image where's the problem here property asset which is declared on okay
10:14property asset which is declared on okay
10:14property asset which is declared on okay so let's go check this out let's go
10:16so let's go check this out let's go
10:16so let's go check this out let's go check um what this might be getting
10:19check um what this might be getting
10:19check um what this might be getting caused by I have a feeling this is to do
10:22caused by I have a feeling this is to do
10:22caused by I have a feeling this is to do with the query so let's go check the
10:24with the query so let's go check the
10:24with the query so let's go check the queries out and you'll notice there is
10:27queries out and you'll notice there is
10:27queries out and you'll notice there is an image fragment on here let's see if
10:29an image fragment on here let's see if
10:29an image fragment on here let's see if there's one for um let's stop this okay
10:32there's one for um let's stop this okay
10:32there's one for um let's stop this okay we'll accept what it's got so far that's
10:34we'll accept what it's got so far that's
10:34we'll accept what it's got so far that's fine um and we will look at the herob
10:39fine um and we will look at the herob
10:39fine um and we will look at the herob Block so if we go to herob block inside
10:41Block so if we go to herob block inside
10:41Block so if we go to herob block inside of here I notice that there is a image
10:44of here I notice that there is a image
10:44of here I notice that there is a image fragment and a rich text fragment now
10:46fragment and a rich text fragment now
10:46fragment and a rich text fragment now this is the way that we handle Gro so if
10:48this is the way that we handle Gro so if
10:48this is the way that we handle Gro so if we go one below we were going to say
10:50we go one below we were going to say
10:50we go one below we were going to say content with image block let's take that
10:52content with image block let's take that
10:52content with image block let's take that for now um and we want the that's
10:55for now um and we want the that's
10:55for now um and we want the that's actually exactly what we want um
10:59actually exactly what we want um
10:59actually exactly what we want um so let's just finish that one off
11:01so let's just finish that one off
11:01so let's just finish that one off perfect and then let's take this content
11:03perfect and then let's take this content
11:03perfect and then let's take this content with image block and Pop That Into the
11:05with image block and Pop That Into the
11:05with image block and Pop That Into the page builder wherever that is is it down
11:08page builder wherever that is is it down
11:08page builder wherever that is is it down here
11:15yep perfect now if we pop
11:15yep perfect now if we pop back um and we run this
11:19back um and we run this
11:19back um and we run this again so let's run the PN run
11:23again so let's run the PN run
11:23again so let's run the PN run type see if it breaks and we'll go
11:26type see if it breaks and we'll go
11:26type see if it breaks and we'll go through if it breaks as well cuz that'll
11:27through if it breaks as well cuz that'll
11:27through if it breaks as well cuz that'll be really helpful um this just means
11:29be really helpful um this just means
11:29be really helpful um this just means that everything that you're writing up
11:31that everything that you're writing up
11:31that everything that you're writing up is actually like fully fully typescript
11:33is actually like fully fully typescript
11:33is actually like fully fully typescript and you'll see bada bing bada boom it
11:36and you'll see bada bing bada boom it
11:36and you'll see bada bing bada boom it just went green which is great news so
11:39just went green which is great news so
11:39just went green which is great news so that's worked and it was all down to a
11:40that's worked and it was all down to a
11:41that's worked and it was all down to a couple different files so the query file
11:42couple different files so the query file
11:42couple different files so the query file with sanity um and making sure we're
11:45with sanity um and making sure we're
11:45with sanity um and making sure we're using these fragments the reason why
11:46using these fragments the reason why
11:46using these fragments the reason why these fragments are so useful is at
11:48these fragments are so useful is at
11:48these fragments are so useful is at first it seems like a lot of fuss and a
11:50first it seems like a lot of fuss and a
11:50first it seems like a lot of fuss and a lot of hassle but as the website scales
11:52lot of hassle but as the website scales
11:52lot of hassle but as the website scales and you have like 600 700 Pages um this
11:55and you have like 600 700 Pages um this
11:55and you have like 600 700 Pages um this is not a lot of hassle what is a lot of
11:58is not a lot of hassle what is a lot of
11:58is not a lot of hassle what is a lot of hassle is trying to figure figure out
11:59hassle is trying to figure figure out
11:59hassle is trying to figure figure out why your uh queries are timing out
12:02why your uh queries are timing out
12:02why your uh queries are timing out because you're pulling so much data in
12:03because you're pulling so much data in
12:03because you're pulling so much data in one go um so I definitely recommend
12:06one go um so I definitely recommend
12:06one go um so I definitely recommend doing
12:06doing
12:06doing this um and as you can see this is now
12:09this um and as you can see this is now
12:09this um and as you can see this is now all wired up let's go on to Arc and
12:12all wired up let's go on to Arc and
12:12all wired up let's go on to Arc and let's go into Local Host
12:15let's go into Local Host
12:15let's go into Local Host 3333 which is the sanity
12:173333 which is the sanity
12:173333 which is the sanity environment and inside of here we
12:21environment and inside of here we
12:21environment and inside of here we should give it a couple seconds oh here
12:24should give it a couple seconds oh here
12:24should give it a couple seconds oh here we go let's log
12:26we go let's log
12:26we go let's log in I'm really hoping it doesn't come up
12:29in I'm really hoping it doesn't come up
12:29in I'm really hoping it doesn't come up with the
12:31with the
12:31with the or Okay cool so let's go to structure
12:35or Okay cool so let's go to structure
12:35or Okay cool so let's go to structure let's go to Pages we can do this through
12:36let's go to Pages we can do this through
12:36let's go to Pages we can do this through the actual presentation um but for
12:39the actual presentation um but for
12:39the actual presentation um but for example let's take this page and let's
12:41example let's take this page and let's
12:41example let's take this page and let's hit the
12:42hit the
12:42hit the plus what is this get rid of
12:45plus what is this get rid of
12:45plus what is this get rid of that and let's
12:47that and let's
12:47that and let's do content with image so this was it so
12:50do content with image so this was it so
12:50do content with image so this was it so we know that if this works this is
12:52we know that if this works this is
12:52we know that if this works this is actually working so write content with
12:54actually working so write content with
12:54actually working so write content with image content with image title Rich t
13:00image content with image title Rich t
13:00image content with image title Rich t nextt let's choose an image from
13:01nextt let's choose an image from
13:01nextt let's choose an image from whatever's in the uh
13:03whatever's in the uh
13:03whatever's in the uh environment oh that one's not so good
13:06environment oh that one's not so good
13:06environment oh that one's not so good let's pick one from
13:08let's pick one from
13:08let's pick one from unsplash uh let's go for this nice
13:12unsplash uh let's go for this nice
13:12unsplash uh let's go for this nice coffee looking
13:13coffee looking
13:13coffee looking thing let's wait for that to
13:16thing let's wait for that to
13:16thing let's wait for that to download and then we're going to hit
13:17download and then we're going to hit
13:17download and then we're going to hit publish and this
13:26should lovely little bit of Rich text to
13:26should lovely little bit of Rich text to compliment
13:42battery okay and what we're going to do
13:42battery okay and what we're going to do we're going to hit we can open this so
13:44we're going to hit we can open this so
13:44we're going to hit we can open this so we can actually go back pages go into
13:47we can actually go back pages go into
13:47we can actually go back pages go into here and open it this way opening
13:49here and open it this way opening
13:49here and open it this way opening presentation should open straight away
13:51presentation should open straight away
13:52presentation should open straight away and we'll see if it's in there
14:03ooh component not found with block type
14:03ooh component not found with block type content with image now let's find out
14:04content with image now let's find out
14:04content with image now let's find out how we fix that so remember how we had
14:07how we fix that so remember how we had
14:07how we fix that so remember how we had this page builder here the problem is
14:10this page builder here the problem is
14:10this page builder here the problem is that we have another page builder here
14:12that we have another page builder here
14:12that we have another page builder here that we forgot to put it in so if we pop
14:15that we forgot to put it in so if we pop
14:15that we forgot to put it in so if we pop down a level you'll see that we have
14:18down a level you'll see that we have
14:18down a level you'll see that we have content image with block or
14:21content image with block or
14:21content image with block or content with image block and now we've
14:23content with image block and now we've
14:23content with image block and now we've added those two so again it's just
14:25added those two so again it's just
14:25added those two so again it's just literally um the actual string and then
14:29literally um the actual string and then
14:29literally um the actual string and then this version that is the uh actual
14:32this version that is the uh actual
14:32this version that is the uh actual component itself so in theory that
14:36component itself so in theory that
14:36component itself so in theory that should have just worked and we'll see if
14:38should have just worked and we'll see if
14:38should have just worked and we'll see if it has and there you go that is a full
14:42it has and there you go that is a full
14:42it has and there you go that is a full sanity block being built for a page
14:44sanity block being built for a page
14:44sanity block being built for a page builder from start to finish uh it took
14:46builder from start to finish uh it took
14:46builder from start to finish uh it took us less than 15 minutes which is great
14:49us less than 15 minutes which is great
14:49us less than 15 minutes which is great um but this is a very very simple
14:50um but this is a very very simple
14:50um but this is a very very simple version as your website scales this will
14:52version as your website scales this will
14:52version as your website scales this will scale with it and this will be very very
14:54scale with it and this will be very very
14:54scale with it and this will be very very good for building these kind of websites
14:55good for building these kind of websites
14:55good for building these kind of websites but this is the Baseline for building
14:58but this is the Baseline for building
14:58but this is the Baseline for building these blocks and what you can
14:59these blocks and what you can
14:59these blocks and what you can essentially do with the project um yeah
15:02essentially do with the project um yeah
15:02essentially do with the project um yeah have a great day take care bye-bye
Questions answered
Editorial answers from the original Roboto page.
What is Turbo Start?
Turbo Start is Roboto Studio's open-source Next.js + Sanity boilerplate, structured as a pnpm monorepo with separate apps for the Next.js website and the Sanity Studio. It's designed to give teams a working page builder, type generation, and a sensible starting structure on day one rather than wiring everything from scratch.
Read the original ↗How is Turbo Start structured?
Turbo Start is a pnpm monorepo with two main apps, `studio` for Sanity and `web` for Next.js, plus a shared UI package. Schema files live as `.ts` inside the studio, and matching React components live as `.tsx` inside the web app. The root `package.json` stays deliberately small so dependencies belong to the workspace that uses them.
Read the original ↗How do you add a new page builder block to Sanity in Turbo Start?
Create a schema definition in the studio app, register it inside the page builder array, run `pnpm run type` to regenerate the TypeScript types, then add a matching `.tsx` section component in the web app and wire it into the page builder block resolver. After that the editor can place the block from inside Sanity Studio.
Read the original ↗How do you create a Sanity schema?
A Sanity schema is a `defineType` object that lists fields like title, rich text, and image. In Turbo Start the schema lives next to its sibling components, you generate types from it with `pnpm run type`, and you reference it from the page builder index so it shows up as a block option in the studio.
Read the original ↗How does Sanity work with Next.js?
Sanity stores content and exposes it through GROQ queries; Next.js fetches that data and renders it server-side. In Turbo Start the two are split into a monorepo so you keep schema, type generation, and rendering in one repo while still deploying the studio and the website separately.
Read the original ↗Should I use pnpm with Turbo Start?
Yes. Turbo Start expects pnpm, and that's the reason the workspaces and dependency hoisting line up correctly. Using npm or yarn will produce duplicated installs and inconsistent lockfiles, which gets painful fast across many Sanity and Next.js projects.
Read the original ↗Why does Turbo Start use GROQ fragments for queries?
Fragments like `_image` and `_richText` keep blocks composable, so a hero block and a content-with-image block can share the same image query without duplicating fields. It feels overkill on a small site, but at 600 or 700 pages it's what stops your queries from timing out by over-fetching.
Read the original ↗Scope and context
- Video authors are credited by the original Roboto page; individual transcript speakers remain unassigned.