Integrating Next.js and Wagtail: Building a Headless, Content-Driven Website

This video is from Wagtail CMS 2024 .

Integrating Next.js and Wagtail: Building a Headless, Content-Driven Website
0:58:54
Published July 11, 2024
1,368 views

In the fast-paced world of web development, creating a scalable and content-driven website has never been easier. With the perfect combination of Next.js and Wagtail, you can build a headless website that's not only easy to manage but also dynamic and efficient. In this tutorial, we'll take you through the process of integrating Next.js and Wagtail, step by step.

📹 Related Videos To Watch Next:

â–¶ Improving weather warnings and climate information dissemination in Africa https://www.youtube.com/watch?v=rtuN9...
â–¶ Quick video tour of Wagtail 6.0 https://www.youtube.com/watch?v=_Vg_l...

Wagtail future proofs your CMS system, as it’s open source, continuously updated and built on Python, one of the most popular global programming languages, used widely in machine learning and big data. So you’re always ahead of the curve when it comes to CMS platforms

Wagtail is the #1 choice for accessibility, is scalable and most importantly, secure.

👉 Get started with a FREE Wagtail CMS TRIAL: https://wagtail.org/get-started and see how easy it is to build a website that works for you.

📊 Read why Google, NASA, and the British NHS, are powering their digital estates with Wagtail: https://wagtail.org/about-wagtail/

🎥 More Wagtail Videos: https://www.youtube.com/watch?v=cne2kxemMAQ&list=PLfwZ-fob20cPvSQ_v1hkjto8BAPN21tLJ

📣 Follow us on social:

#WagtailCMS

Summary

The speaker shows how to build a headless, content-driven site with Wagtail as the CMS and Next.js as the frontend. They demonstrate a Wagtail-powered CMS setup, configure a Next.js project with the CMS API URL and API key, and use Wagtail.js to fetch pages, images, documents, metadata, lists, and individual blog posts. They explain how to match frontend routes to the CMS URL structure, configure caching and remote image hosts, define TypeScript types for custom CMS responses, and render Wagtail rich-text and streamfield-style blocks through reusable React components. The walkthrough ends while rendering a blog post body dynamically, after replacing hard-coded content with data returned from the CMS.

Key takeaways

  • Wagtail provides the editing interface and content, while Next.js renders the public website and handles frontend performance.
  • A Next.js project needs the CMS API URL and API key configured in environment variables, with the key created through the CMS dashboard.
  • Wagtail.js wraps the Wagtail API with a dependency-free client for fetching pages, images, documents, lists, searches, and individual posts.
  • Frontend routes must correspond to pages that actually exist in Wagtail; mismatched paths such as `/tutorials` cause fetch errors until they are corrected.
  • Custom Wagtail page and block structures should be represented with TypeScript types so the returned CMS data can be used safely.
  • Rich text, headings, images, call-to-action blocks, and other body content can be mapped to reusable React components and rendered dynamically in Next.js.

Summarised automatically from the transcript.

Chapters

  1. 0:00 Headless Next.js and Wagtail Overview Introduction to the talk, the technology stack, and a preview of the content-driven website.
  2. 3:48 Wagtail CMS Setup Options Comparison of using a hosted Wagtail CMS with creating and configuring a Wagtail project from scratch.
  3. 5:21 Next.js Starter Project Cloning the Next.js template and reviewing its role as a starting point for the integration.
  4. 8:32 CMS API Credentials Configuring environment variables and generating an API key for access to the Wagtail CMS.
  5. 10:50 Fixing CMS Route Mismatches Diagnosing and correcting a broken tutorials route caused by the CMS using a blog path instead.
  6. 13:11 Wagtail.js Client Integration Setting up the blank frontend project and configuring Wagtail.js to fetch CMS data.
  7. 17:00 Wagtail API Queries and Page Types Explaining page types, query parameters, metadata fields, and Wagtail.js abstractions for retrieving content.
  8. 20:06 Fetching Homepage Content Loading blog data into the Next.js homepage while addressing caching and request issues.
  9. 24:44 Dynamic Blog Listings Replacing hard-coded cards with CMS-driven blog data and introducing listing and sorting logic.
  10. 27:02 TypeScript CMS Models Defining TypeScript types for the CMS response and resolving typing problems in the frontend.
  11. 32:24 Media URLs and Image Configuration Configuring Next.js and Wagtail.js to correctly resolve images served from a separate CDN.
  12. 38:30 Blog Detail Pages Fetching an individual blog post by slug and preparing its metadata and full content for rendering.
  13. 45:39 Rich Content Rendering Building CMS block components and using a block renderer to display Wagtail rich text and structured content.

Transcript

8,894 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:00

Hello there, welcome. In this video I'm going to show how to build an awesome website using Next. js and Wagtail. So we are going to be building a headless content-driven website. So if you don't know what Wagtail is, Wagtail is a leading open source Python framework which is really great at creating and managing content for small and larger websites. Next we have Next. js which needs no introduction It's a production ready react framework used by a lot of companies outdoor. So let's just start Remember I said Wactail is really great at managing content so you have some insights from people we have already um worked with and we have their website which you can check out So the technique used to build this website is the exact technique we are going to show you. So first we have Bridge

0:45

Labs which we build their inside page using this same technique and it's as you can see it's Like the CEO commented that it's really great at managing website without the need of a developer. And next we have like TrailBlock. Yeah, this block. This block was built using Quagtail and Next. js. So as you can see On this website all the content is being pulled from a Wagtail CMS and we just have to render it properly. So now let's just go to the next section So here we are going to have a preview of what we are building and let me just go ahead and open that. So this website is built with the latest version of Next. js and the content is being manage or by wagtail by wactil CMS so here is the website we have um

1:31

most of this content is being put all of this dynamic content is being pulled from the Wagtail CMS or Wagtail backend. So as you can see this is a blog post and you can scroll the website looks pretty good, pretty decent. It's mostly for demonstration and yeah So we can definitely improve some of the things here. So if I click on all tutorials, you're going to see the content loads pretty fast. And we have the list of blog posts you can filter Unfortunately there was no blog post during like this month and you can just reset you can filter by category all of this is being done Yeah, you can filter by beginners, intermediate and you can see it's pretty fast and you can also order by

2:16

um random A to Z to A. Yeah, you can add other, and as you can see, the performance of the website is really great. Next, if you can click on the blog post and you're going to see it's going to load the content, dynamic content from the back end. And like I said, this content is all from Wagtail. So we have a really good um editing interface where we can pull include all of this content so from the rich text to the video embed to Code blocks to like this is a code block to anything we want so we can check out another blog post. Um yeah as you can see this is pretty good like all of this is being managed in the back end and we are going to show you how that is being done Um

3:01

next we let's just check one more and yeah there we go so looks pretty awesome so you can also search we have some searches so when you search it does a search in the back end so okay one block goes Um headless. Alright, nothing found. And let's just go with Django. As you can see, it's really good. It responds very fast. And yeah, the performance of the website is great. So this is due to the power of NextGS. So yeah, I think that's it for the demo. If you want to see like a deeper dive, you can watch this video. So for now, let's go step one Alright, so now we need to set up a CMS. We are going to talk about two main approaches. We are going to be using Trailer

3:48

CMS, which is a Wagtail-powered CMS. And we are also going to like walk you through the process of setting up your own Wacktail website from scratch. So let's go ahead and just um do this, like start with Trail CMS. So for Trayous CMS Cool, so this is the video. So this video is going to show you how to set it up. I just wanted to like walk you through the steps. Now um the next approach we can use is actually um Installing and setting up our Wacteo website from scratch. So this was done by um Thibaut Colas, one of the core contributors of Wacteo. So he did a workshop which was pretty good at like explaining the different steps to set up your wactail cms for headless for a web headless website so as you can see

4:35

Here is a repository and it's yep, I'm just checking. Yeah, here is a repository And as you scroll, we have like all of the instructions to set it up. So you have like some requirements here and some introduction here in case you need to learn, you need to know. So you have to like pull up your terminal, create a new project. After you create a new project, you have to like install Wagtail and you actually start your Wagtail website. Once you do that, you install all the requirements just like a normal Django project And you click your super user, you manage and you run your server to log going to like the dashboard to manage your your your website. So once that has been done

5:21

You're going to be like this website is going to be come with some data which you can already just cook skim through and start managing it just very similar to what we have on Trader CMS. So you see how the data is being it's working and how everything works together. Alright so next um so we have gone through like setting up with trailer and you can also definitely set up your own work to website from scratch but for this tutorial like I said we are going to be using trial CMS since it's easier and you don't need any technical skills for that So now what we are going to do is we are going to set up our next JS website. So there are two ways you can do that. You can either set it up using the template we created. So the template just have like some like the boiler

6:07

plate code we use to actually like build a nextjs plus wagtail website so it's going to show you how to fetch um how to structure your your components or how we structure our components how we fetch our data with um Wagtail and we are using a very cool um Package we created which is called Wagtailjs. So Wagtail JS is a client that we use to abstract the data fetching for from a wagtail base CMS. So we are going to go through this So yeah, let me just close this and we continue. So like I said, first step we are going to use the next JSP block just like template, like next JSP block template. So we can just like Make things go faster and definitely you can set up your own website and use the same approach or just use this template as like

6:57

a reference when building your website Alright, so this is the next JS template and I'm just going to pull up my terminal and we can clone it. Okay, so um let's clone it I'm using SSH by the way, but you can definitely clone it using your preferred method Clone yeah, so while that is cloning, like I said, the advantage of this is that we already show you how like we do a data fetching and especially how it's been abstract abstracted with the help of Wagdeo GS so yeah that has been cloned I'm just going to open it my code editor

7:46

Oh, you need to cd into the project All right Yes. Alright, so as you can see, here is a project file. So the main branch already has like a complete version of the website. Like yeah, I think we should just go ahead and run it But before we run it, let me just install the dependencies and install so why that is installing so there's one thing we need to do first like This um env we need to set up our own env. So I'm just going to create my own env

8:32

file. Once I create that, I'll just copy this and Set that up here. So the two things we need to really pay attention is um is a CMS API URL and the API key. So The API URL is where um is it the API URL, yeah, it's the URL to RCMS the base API URL and next we have like the API key which is what we need to like access uh like uh API so now um Let's let me walk you through how to create this and we are going to go back to our trio dashboard. So this dashboard now what you want to do is you have to come here You have to go to profile. Once you're in profile, you come here

9:18

API access. So this is going to help you create like the API key. So I'm going to do this. Um yep. Wag deal Worktail space demo key. Alright, so I'm going to select the website which I want to grant access to this API key and it's going to be the Wackdale Space website so i create api key and here is my api key so i will just copy that yeah and paste it here yeah so i have my api key set up And I need to like know the URL to my website. So the URL to my website is this one. So wactilspace. trader. com So there you go.

10:04

Backdospace. trail. com, yeah, I think that's it Yep, so now that I have my API key definitely if you close this you won't have access to it again But you can revoke the API key and delete it, so yeah, no issues and recreate a new one. So I have that set up and let me check my dependencies have already been installed. So if I run the project. All right, so let's go to local host Yeah, you're going to see that it's a website we um previewed earlier so this website only has all like everything like the structure and the Methodology we use

10:50

actually like integrate Wagtail with Next. js and we deployed it with VSL. So yeah, so you can see it's pulling the content from my own CMS. So these are the default content we have. So if I click on view all tutorials all right let me seem like there is an issue oh okay yeah I know the issue the issue is Yeah, let's click on view auditorial. So yeah, there's going to be an issue because on my blog there is no like this part. So we are using these parts after I fetch the pages that are found in under tutorials but if I come to my worktail cms here we have no page that exists with that part

11:37

so that's why We have an error, so this is going to be yeah, so we have an error there. So to make this work, you're going to have to come to the fetching here. Um so this is bad And this is why yeah, so what is happening is that this is written in blank because on a CMS like I said we have no page that it's um exists on slash tutorial so for example in our case we have a blog page and you're going to see that the slog is slash blog so let's go ahead and change tutorial to um anything that has slash tutorial to slash blocks so yeah

12:24

I'm just making sure I'm selecting the right ones. Yep, so slash blow So this action link that alright so I'm just going to replace that and I 'm going to go back and just Make sure we refresh so that that's being added. Alright, now I have slash block and as you can see it's pulling the content from my CMS because the um Now the page I'm requesting in slash blog exists so I can click on this and we are going to see how it's been presented here on our next JS website. So very similar to what we have. So we probably just need to like add more content here.

13:11

And yeah, you can play around with the CMS and add more content. So now um like this is the template. So what we can do now is um on this repository we have like the front and the main front end files which you can use to start like your own project so I 'm going to go to that project so we have like a blank canvas or like a blank project to just start and I'm going to show you how to pull the data for each pages All changes and I'm going to go to this branch. Yeah, so the front end branch has the the starter code which we should not have like all this data fetching logic in it and Is my server, yeah. My server is running basic compiling. Alright, yeah.

13:56

As you can see, this is the starter template and it has like just the blank website with no data feature. These are hard-coded data. So If we click here, we shouldn't be okay. Yeah, this is just like dummy data have been rendered. So now what we are going to do is we are going to like use this template to actually like integrate our website. So We are going to I'm going to use this as a reference to make things go a little bit faster. So the first thing we need to do is we have to set up like our Integration with the CMS. So we already have like our API key, a API URL, and the base like our API key setup or an ENV5 setup. So I'm going to come here and we need to create like

14:42

everything. needed for the data fetching so if I come to CMS here you're going to see the boilerplate front end comes with some code gel in slash cms so you're going to see that we have like um we are using wactils js and we are importing like some few features from some few um So as you can see we have Wagtail. js and we are importing some of the um items from Wagtail. js like functions and types. So We are loading our API key and our API URL next and Wacttails. js as you can see here provide us with this CMS client which is just like set up the client that is going to like pull in the data.

15:29

So We have the base API URL. We have the API part media base URL in case you have this and in case your data is being served over like a CNS C C N CGN And the website like the media URL changes so it means it's not still going to be like similar to the base URL, but it's going to be using like a CGN URL. You have your headers in case you have any, and you have your cache mechanism Now as you can see here we have set up like a base URL to the CMS API URL. Currently it's um the trio API URL But definitely you can set up your own Wacta website from scratch and use this approach because yeah what you want to pass like is just like the base URL to your API. Now you pass like the

16:14

API part and then in case your website has any headers that need to be passed you just pass it here so in our case using the trail CMS you need to like pass your API key so this is how we pass it here Now we have initiated a CMS client. Now we use it to fetch different pages and different content from our website. So if you scroll here, you're going to see like a different technique to use to fetch pages to fetch images and fetch documents and you can retrieve one you can retry for an image or a document so these are different functions documented here so we are going to see how that is being used So for us now for us like um pull out all the pages like all the um the blog pages so

17:00

on trio CMS let's just go there like on Wachtel you have different types of pages so if I go to my home page and i try to create like a new page you're going to see that for these cms for trail cms we have like three types of page if you have a flex page flex page home page we blog page but for this to work I need to be in the blog page yeah the like each um each page Like in Wacta you have to configure the different pages that can fall under specific page. So when I was under my homepage, so that I had like three different pages but when i'm under my blog so creating a page in blog you're going to see that i have two type of pages i have a flex page which can be like an about page

17:45

And I have a we blog page which is like a blog page with like the rich content editor or editing interface. So now um Yeah, what we are doing is that for us to pull like all the metadata for our blog pages, we are just like um using this like the CMS client fetch page, we pass in like what we want. We want like the English pages we can order it randomly and we are specifying the type of the page but yeah if you want to just pull or any type of page you just need to get rid of this line And you just have also have like look into um this um the CMS quip like the documentation of the the of Wagtail JS know the different options you can use so type offsets order site

18:31

search and everything here so this is very big like the where is this from this is actually From let me just open that in the other tab. So what Wagtailjs is doing is that WactailJS has created an abstraction for this um API usage guide so it provides you with all the queries all the techniques used to fetch if like from a CMS or Wactailbase CMS but it just abstracts it in different functions and just simplify the works the work for you so yeah by the way under the like work tojs uses zero dependencies it uses the fetch api to pull the data so you don't have to worry about like any dependency issues

19:17

so yeah like i said i like i said you have like the different documented And Wagtail GS also we kind of like documented most of it. So if you want to learn more about the different features, you can just read through the Wagtail API usage guide And you can also inspect like the Wac2. js documentation here. So you have the different options to know how you're pulling data. So here, like I said, I'm pulling all my blog pages with their metadata I'm pulling all my blogs so as you can see I'm pulling English pages, ordering them randomly, pulling only the blog pages and I'm specifying the fields I want to pull so the headline, the search description, the image, the category and the date published. So this kind of like what we are going to use to display the list of blocks

20:06

And I'm using this to actually get a single block. So yeah, I'm using the CMS client fetch page, passing the slug of the page, and I'm pulling like all the fields from that block. So Yeah, here is what we have. So we already have like these functions ready to be used. And we can now come to uh home page like of an XJS website and you can try to like pull some data to display so yeah we are currently using um Next GS the app directory so as you may have noticed okay we are going to come here and we need to like fetch some data so let's just go and like I said it's this template is pretty useful because you can just see the way we do it and you can just like copy the code and

20:51

adjust it to the way you want. So I'm just going to copy copy this and paste it here. So yep um I need to up import all blocks Yep, just import that and it should work. Image is not assigned with type number all blocks This is all blocks right number undefined. So I'm not sure what's wrong here Well I'm going to like we're going to take a look at that later but yeah let me just rename this to blog since we don't have any tutorial pages

21:36

all like it's just a blog for now So these are blogs. Um so you want to pay attention to this because it created like if like next JS has like some caching that goes like um that occurs and If you don't set your caching appropriately, you're going to see that most of the time the data being written is not always written in the latest data. So for this homepage, let's say for our use case, we want it to like revalidate the data everyone has. So that's why we place this here. And yeah, this is what we have. Next, I'm just going to copy the head of this page and so we can pull the data for this page. Yeah, so we have

22:24

And I'm just going to console log it here. Alright, so I have this. I'm not sure what's happening here. Let me just try this. Let me This is yeah, I'm not sure what's going on here. This seems to be right. Let me see if it's actually running though Alright, local host. Let me go back to home because you would be response alright I have an error just checking that now

23:12

this is not it Date publish limit all right there's an issue with this so this like this been um console log from the Wagtail JS package And let's just go ahead and debug this. So I don't know what's going on with this limit. I have one year. And let me just see. Let's see. What's wrong? What's going on here? So all blocks is receiving limit. Limit. Oh yeah, okay, yeah. This is the issue, yeah. Alright, so um seems like I updated this so the limit is this all blocks is just expecting like the limit

23:59

so I'm just going to go ahead and fix this Okay, so this should work now, yeah. Alright, so this function we are pulling like three blocks using the limit to actually limit it And here is how we um fetch it, like call the function with um with next JS, we call it, we wait for the blocks to load and we just like control log it to see what we have So let me just double check that everything is working. Yep, blocks. Alright, let's just refresh this now. Okay, so And I'm scrolling down and as you can see yeah it's pulling all of the data from a trio

24:44

CMS so the introduction introducing trio CMS and all this content by the way like I said how do I know the page structure is because like this is my Wagtail um my CMS website And you can see I have like a slash blog page. Remember when we are using slash tutorials, it wasn't working because we have no page in tutorial. For example, if I put um Tito Reals it won't work because we have no page here so yeah this is the content we have two block and these are the content of the blog so this like a normal wactail website which is rendering it using like um the template the html templating language But now on Next. js, as you can see, we have like this data.

25:29

We have the title. We have everything we need to actually display that on our Next. js front end, so that's pretty cool. And we can leverage the power of NextGS to do a lot of other cool stuff. So once we know that we are able to like pull data from the CMS, we want to come now here Let's just use this as a reference to make things go faster. So I'm just going to use this to actually map through it and render the content to the page so remember like I said this is just like static data that we had coded And now I just want to put in like the dynamic data. So as is blocks, so

26:15

blocks And this should work now, so I I don't have the CMS CMS client And truncate text is actually a function that I'm not sure if it's already here but if it's not here alright yeah this is just a function we use to truncate but i don't think this is actually needed but if you want to write yours you can go ahead and write it all right Mmm so yeah search does not exist property search description does not exist and that property search description does not exist and

27:02

Are we getting something wrong here? Alright. Okay, let me just go ahead and check this. Okay, we need to like fix the typing issues from this. So if you inspect the data that is being returned by this, you're going to notice that there are some few um Depending on the way you customize your CMS you need to like probably type the return type of the data here so I'm just going to like reference here and is a main branch so the main branch we have this yeah so the template the starter template wasn't as some Typing issues so which function is this?

27:47

I'm getting all blocks. So this is the get all blocks. All blocks. Alright, yeah. Let me fix that. So I'll just copy this And you can paste here think I have CMS query all blocks Okay, this type does not we block contents So we need to create this type if it does not exist here we block content does not exist Let's just go here. We should have that. Yeah, yeah. We don't have this.

28:33

So let me just go ahead and create this CMS type. So based on your CMS, you want to probably type this. You want to properly define your type your return type for the CMS to make sure you have to like inspect the return and make sure you just like properly type it For your own CMS, so most of the time it's because like the Ape like everyone can structure their own CMS data Um they want CMS the way they want, so you want to properly type them. So these are the typing for trailer CMS and yeah, so the Wagtail JS probably just provide like a generic typing for most of them, and that's why when you see Well this has already been fixed by the typer. That's why um we had some typing issues here.

29:19

So I'm just going to come here and pull those types So we block content. I have created most of the types here. Yeah. So these are like I said, these are the types for 3D or CMS. If you're using your own CMS with some specific or unique type term specific or unique typing or structure of your models you have to like properly type them here so I have that setup all blocks I need to all block is importing the block content so this does not exist no doesn't seem to exist in the type here Alright, so I'm just going to look for where we have vBlock content. Alright, this is v

30:05

block content. Might as well just copy everything here Alright, so index. d. cs. Yeah. Alright, so this should fix all the typing issues. And I'm just going to update this template to have like the latest updates like the latest update for the CMS and the type so that once you're doing it you should not face like most of these issues so yeah I have updated that the blocks And I have everything set up with the typing. So now there should be an error here. Yeah I'm just going to update this template to make sure it has like just the type so you won't face all of these issues but it's good that we are on the video and I'm showing how the everything is set up

30:51

and how to private like debug everything but yeah so this should work now and this should work now we know like a CMS like a blog page has a headline search description and all of this cool stuff and if you come here you're gonna see that For trail CMS, like the VBlock content in your blog page, you have like a rich text, simple rich text, full rich text, CTA block And we are just trying to like properly type the data that is being returned from our CMS. For example, this you just need to like look through the data that is being returned and you properly type them. So Um we leverage some of the base type that have been written or the base type from Wactail. js actually create this but yeah you have to like properly type your return

31:37

object since we are using TypeScript obviously But if you're using JS then JavaScript you won't need you just need to like double check and make sure what you're trying to infer or what you're trying to get actually exists so yeah I have everything properly typed here and yeah probably have the typing here and I have my all blocks here so we would just go ahead and double check here yeah so everything seems to be fine here And if I come now to my NextGS website, okay, work too space, we need to like so invalid props, so this is a Next. js problem needs like set the host that is accepted so CMS

32:24

all right well right also just copy this Next. js config all right. So copy that. So basically we are just passing like the we are just making sure that um this like nextjs can resolve like we're just setting the URLs or the image media URLs that nextGS should accept so that should work now I don't know if I need to restart the server Yeah, alright, that works now. Okay, so if I scroll down here, you're going to see I have this, but it seems like for some reason the images are not returned

33:11

upstream image field to clear just run it Okay for some reason the images are not working but let's just go into our CMS and update that Let me see I'm not sure why that is not pulling but yeah let's just go ahead and add a new image All right. Yep, I don't know if there's something here

33:58

for me. Well yeah I'll just use cover update good blog blog page let's just update the images of our blog Not sure why this is not pulling for now but yeah let's just change it and see if that works so I change it And I pop the shoe Introducing Trio CMS that the image seems to be working copy image URL

34:43

this is it cdn dot dot so let's see History Webb space. Okay, the year wait. HTTPS work to space CMS media alright we are not constructing the URL to our image appropriately so we have slash medias okay the base is supposed to be cdn. trail. com yeah but now we are passing like work tail space so let me show you how to set that up so we have let me just copy this Alright, we were not constructing our URLs appropriately so

35:32

Ah yeah I think we have something like let me check the documentation media base URL alright media base URL Oh okay it's actually a URL. Like I said I'm just going to update these templates make sure that these errors you don't face them but yeah I think this should work all right trivial Trailer.

36:17

com okay let's preview now media bas not end with Oh yeah, must not the error says media base URL or API part. So this error has been thrown from the Wagtail. js package. So yep, not any that And let's see if that works now. Alright, yeah, that works. So um for example like for the trio CMS for the trio CMS if you can see the url like um let's just go here if you can see the url of um the image is actually different from my base um URL so that's why I needed to like set like a custom media base

37:06

URL because coinly the trio The trio CMS websites assets are being solved over a CGN. So like this is the default settings. So that's why I needed to like update settings. The base share of my media files are different. Now if you take a look here you're going to see that that's why my images were not rendering because by default it was inferring the base it just assumed the base of your image What will I do? The same like the base year of for your images were the same as your website. So as you can see, we have waptalespace. com, so which is using the same, so yeah We have fixed that

37:51

and next we should just go here. So we are able to like pull data from our website and yeah this is the data that has been returned definitely we we want to like probably do some truncation here to just make sure either it occupies just a single line or just multiple lines So well that's just a CSS issue. So you can definitely take care of that. And based on your design, you're probably going to style it or have it displayed differently. So yep And yep, what is constructing the image is this CMS client get media source so it helps you to like build the URL of your image of your images Now yeah we have this working now if we go to like slash blog

38:39

we have like just the default like this just random data that has been written now but yeah before we go to like stash block let's go to like our block so we did not name okay we already named this so probably we want to name these two blocks let's just go ahead and name that two blocks um Navbar okay yeah let's just go ahead this should be blocks because we don't have an instruc page So yeah, if I come here and I click on blogs, yeah, we are taken to the blog page, but this is still dummy data, so we need to like pull the data for our blocks and list them all of them

39:25

here so yeah we're going to go to like slash blocks No this is blog, this is the page and we just need to like render the data of these cards in yeah the list so it's pretty the same thing pretty much the same thing as what we just did but we'll probably just increase the limit so now um mc yeah let's go here And yep. So there is a lot going on here because for this we I have like some filtering logic, like you saw on our final

40:10

website, we have some filtering logic here. If you want to implement the filtering logic, you just check out the code how that is being done. But let's just like keep the tutorial short and I'm just going to like show you how like basically is the same thing. So we are just going to copy the code from here and just do the same thing and render it so slash blog. We have that, we have this, and now um we have this So search block

40:55

new, you can just add that new is Okay, so block page block page and yeah so let's just say this let's set this to 10 but we don't have ac we obviously don't have 10 blocks so this won't matter a lot but yeah we have that set up And we just need to like render the same thing. So I'm just going to copy what we have on the home page because it's pretty much the same thing. Copy and I paste this here Mmm missing something yeah it's not copy

41:42

it quickly Okay, so I need to import the CMS client and yeah, this should work now Yeah, as you can see it's displaying all of the blocks and since we have just two blocks well there's not much to be displayed here So this logic the sorting and category and by date like this sorting depending on your use case and what you have to sort you need to like do that and figure out the way you want to do your sorting but as you can see on this template we have like we show you how to like do some simple sorting and which works pretty well like on the demo we saw So yeah, based on your sorting you need to like do what you want to do.

42:30

So now let's go to the blog page and we should show you how it's like render the content on the blog page. So this one should be different but yeah so this is a slug slash block and I'm yellow so This function this get page content is what helps me to actually pull the content from my blog so get blog And all blocks, which is a function we have been using, like this all blocks. So it's what we have been using to actually like pull content. So very same thing. I'm just limiting it to three and this get

43:15

block. Let's just make sure We are using the updated version of the getBlog so CMS and getBlock all blogs Get blocked yeah just making sure this is properly typed and we're using the right one CMS yeah get blocked yeah definitely we were we're supposed to face some issues The type should probably exist. Yeah, so This should work now. And we have this. So we have a page get page content which gets the block using the sluck of that page. And we just get like some random blocks which we are going to display as recommendations.

44:05

So once we have that set up, we need to Once we have that set up, we need to properly display the item from the block. So we have this setup. We need to just Copy this and make sure we are rendering it the right we are fetching the right data so yeah just into spaces but I think we might have some type yeah issues so the language I need to properly type is alright we have long we have string so you just need to update this type So we have long

44:50

we have pad and we have slug so yeah so this works now just need to console lock and make sure we are getting our block very well So if I refresh, if I go to a single block, we should have that. So I'm just checking if I'm pulling the data alright. Yeah. We are getting a block with all the body content. So yep So let's just go over this function. So this get block, this get a single block function actually pulls like Fetch for a blog based on the slog and we just have like some other parameters we are passing like the cache and yeah what we are what's specific specific about this page is because we are for the fields We are pulling everything in that page so all the fills that can be written by the API.

45:39

We are pulling it and now we just need to grab like render it correctly so that's why you're going to see that this data we not just have like the metadata but we have images we have authors we have category we have body with all the data and yeah So there we go. We have this setup, we are getting the data. Now we just need to figure out we just need to figure out how to render it. So We went ahead and created like some components which is this component. So if you come to your component Alright, we the temp that is not included in the template, but yeah, let's just create that.

46:25

So in the components we are going to create a comp we are going to create a component that can render all of this content then like used like nicely on our front end. So we just need to come here and see how it was done. So CMS. Let's create a folder CMS Let's create a folder CMS in it I have Atoms dot C Sx Blocks. Blocks dot tx and index. ts all right so we have that set up

47:13

let's copy this as atoms So this is just like a custom image so that when we receive like an image from the the CMS we render it this way using the Next. js image Is I copy that in the blog that's puts me in the atoms alright blogs Now the blocks has a lot of things going through in it

47:59

Alright, I've copied the content of the blocks just making sure do we have a config here app config what am I using I need the next down that let's see if this is available Doesn't seem to be Let's set up this next public base URL and we did it in a CMSU, yeah. We did it here.

48:45

So I just get called let's use the same approach here CMS DPI key so we need this next public base URL next public base URL and process. dat Yep, so we fix this and we need to fix this Alright, so these blocks are just elements that specify how we render each component from a CMS. So like I said, based on your CMS, this should be a little bit different but it's a good base

49:30

on how to structure it so if you can see like simple rich text we are just setting the html value you need Same thing with full reach text. Now for a CTA block like we are just rendering it as a link. That's the way we want it for our design. Next we have um heading block we are just rendering it in like h2 h h2 h3 h4 tag the way we want it you can definitely style this And we have image block, we're also rendering it the way we want. So this is where you define the way each component for your um from your CMS or from the API is going to be Displayed so we have the banner block and this is the way we have decided to render it. Now we have like this we block renderer, which is a component that is going to receive the component like the content from your body.

50:19

So we are going to pass like the block dot body so as you can see here we have block we block we have like the block block We block. body. So we are going to pass this body content. Now this body content is going to be passed here. So for each item, we are just going to like use it and render it appropriately. So if the custom items you have we definitely want to like figure out how to like just um get like that content type and render it appropriately now once we have that set up we can come back to our blog page And this is a blog cover. Alright, so block page

51:04

So we have pulled we are pulling the data is just like a check to say if the block does not exist we can just return This dummy page or we can definitely return the next jazz not found page so yeah very similar Now yeah, let's update our image to use the appropriate image. So we are currently on this blog and this is it no we are here all right yeah as you can see just using the default image so right now let's just update that to use the appropriate image and we import a CMS client to construct the URL appropriately

51:52

And yeah, now we have the image from the CMS, just like we have here. So we have the image from the CMS. Next we have These links but shouldn't be necessary for this all right so yeah you can definitely do what you want there but the most important thing here is okay let's just render this info Do it's like a nice way. Info Rais that yeah Do I even have it here? But yeah, well this is just how like the blocks have been like the um authors have been rendered. So if you need to render the auto, you can just see the way it's been done here. So now like I said, the most important thing here

52:37

is the We block renderer, so we need to render our blood block content or the body of the page. So we are going to get rid of this dummy content. So we are going to get rid of this dummy content. So now we shouldn't have it here. Alright. Now what we want to do is we just need to render the body using our vBlock renderer Alright, so I'm just passing the content so that our block renderer can now take care of like rendering each item that is being returned from the API. If I come down here, wow, you see, like it's pulling the data and it's running it appropriately.

53:23

So we have content, introduction, body, and conclusion, same thing we have content introduction body conclusion and you can definitely style this the way you want it and for a styling year we have like this layout dot css dot this layout. css that does some custom um that does some custom styling to the component that are being rendered so you might want to check this if you're using like modes CSS modes to actually style your components but yeah these are just some set settings or some CSS or some stylings that we use prop properly render the content so from this you can now start if you have like a custom design oh some different colors for like your text your links you definitely need to like pass them

54:10

yeah so for example let's just update the styling of the link Let's say we want uh anchor links to have color color red. Yep, so now this should be Is this an uncalling? M just double check inspect Okay, it's a bowl. Okay, it's a bowl. It's an anchor link in a bowl. So let's say we just want to pick a bowl to be read so this should work now voila so you can definitely start your your content being rendered from the CMS appropriately and Yeah, it should be good to go. So there's one style that you should really note is this um

54:58

responsive object. So you can check the wagtail issue and know why we are putting this bed these to properly render the iframes that are being rendered on your website so check the issue and learn more about it but you definitely need to add these to properly render iframes So with that said, definitely like to render the tags, it's just like mapping through the tags that have been rendered by your API. So not an issue, just an array, and very similar thing to put drop the related tutorials or blog posts here you just need to like based on your logic you just need like do the same thing we did on the home page and you have this up and running so yeah And this should be it because we have already like we are able to like pull data from on the landing page.

55:46

We can display the data on like a list of pages or the blog pages and we can actually render the full content on our own page like on a single page so once you have this you probably also want like implement like your search logic and the search logic you can definitely see how that is being handled yeah but basic guy what we are doing is we have like We have this that once it like once this input form is being submitted, we do a request to the API and we search. So if you come to Wactail um where is this If you come to the Wacta WacttailJS client, you're going to see that we have like let's just check the queries.

56:32

So CMS queries, you're going to see that we have like a query called search We have a call query call search. You just need to like once you get the keyword, you just need to like pass the query call search here and the um the API wactail CMS is just going to like Search for all the pages, search through all the pages in your website and return the appropriate pages based on the query on the search query. So Yep, you depending on the way your search is, you want to do that. But we have like a simple search that is being done with CSM On next GS year, so yeah, you can definitely check that out as a reference, but yeah, definitely like build the website you want the way you want it. So Um yeah, I think that should be it for this tutorial. So definitely check this template and see how we are doing it and how how we are implementing it, and build your own blog or your own content-driven website

57:25

using Wagdale. So um I'm just going to update this template like the starter front end repository with the updated version of like the um the CMS types for trailer and the CMS client like update this so you shouldn't face like any um typing issues when you're building your own website and so you can just like move faster. So definitely this is a good reference to how to build your website So thank you for watching and you hope you actually had like a great time. So I guess the next thing is just like Going live, you have to like deploy it using the platform you want so you can easily use VSL and for your CMS. If you're using like three or CMS, you won't need to like deploy anything, everything is just already deployed for you

58:13

if you're using your wactillo based cms you definitely need to like deploy the backend and secure it yourself so digital ocean has a good guide which i also use as reference when i i was deploying like when i'm deploying my Django project and there is this cool open source um tool called Pulify which is like an alternative to So you can definitely set it up and also like deploy using it. And yeah, so that's it guys. Hope you have fun building like your content-driven website with Wacht tail and next jazz because it's a really great combination. So um thank you

Questions this talk answers

What are Wagtail and Next.js used for in a headless website?

Wagtail manages the site’s content in a CMS, while Next.js provides the React-based frontend that fetches and renders that content. The result is a content-driven site where editors can work without changing frontend code.

Discussed at 0:00

How can I set up a Wagtail CMS for a headless website?

You can use a hosted Wagtail-powered CMS such as Trail CMS, or create a Wagtail project from scratch by installing Wagtail, creating a Django project, setting up a superuser, and running the server to access the dashboard.

Discussed at 3:48

How do I start a Next.js website that uses Wagtail content?

The tutorial uses a Next.js starter template containing the frontend structure and Wagtail data-fetching boilerplate. After cloning it, install the dependencies and configure an environment file with the CMS API URL and API key.

Discussed at 6:07

How do I connect a Next.js app to the Wagtail API?

Configure a Wagtail.js CMS client with the API base URL, API key or other headers, and optional media and caching settings. The client then provides functions for fetching pages, images, documents, and individual pieces of content.

Discussed at 14:42

How do I fetch blog posts from Wagtail in Next.js?

Use the Wagtail.js page-fetching functions to request pages by locale, type, ordering, search, and selected fields such as headline, description, image, category, and publication date. A separate request using the page slug retrieves all fields for one blog post.

Discussed at 17:45

How do I render Wagtail rich content blocks in a Next.js frontend?

Create components that map each Wagtail block type—such as rich text, headings, images, CTAs, and banners—to the corresponding React markup. A block renderer receives the page body and renders each item according to its type, while the CMS client constructs the correct media URLs.

Discussed at 46:25

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos from Wagtail CMS