Have you ever thought about building something that doesn't require a lot of boilerplate with a tiny bundle size? In this workshop, Scott Spence will go from hello world to covering routing and using endpoints in SvelteKit. You'll set up a backend GraphQL API then use GraphQL queries with SvelteKit to display the GraphQL API data. You'll build a fast secure project that uses SvelteKit's features, then deploy it as a fully static site. This course is for the Svelte curious who haven't had extensive experience with SvelteKit and want a deeper understanding of how to use it in practical applications.
Table of contents:
- Kick-off and Svelte introduction
- Initialise frontend project
- Tour of the SvelteKit skeleton project
- Configure backend project
- Query Data with GraphQL
- Fetching data to the frontend with GraphQL
- Svelte directives
- Routing in SvelteKit
- Endpoints in SvelteKit
- Deploying to Netlify
- Mutations in GraphCMS
- Sending GraphQL Mutations via SvelteKit
Build with SvelteKit and GraphQL
Have you ever thought about building something that doesn't require a lot of boilerplate with a tiny bundle size? In this workshop, Scott Spence will go from hello world to covering routing and using endpoints in SvelteKit. You'll set up a backend GraphQL API then use GraphQL queries with SvelteKit to display the GraphQL API data. You'll build a fast secure project that uses SvelteKit's features, then deploy it as a fully static site. This course is for the Svelte curious who haven't had extensive experience with SvelteKit and want a deeper understanding of how to use it in practical applications.
AI Generated Video Summary
This workshop focuses on using Svelte and SvelteKit to build a GraphQL-based CMS. It covers project setup, configuration, and working with GraphCMS. The workshop also explores fetching data from endpoints, styling with SvelteAdd, and working with blog post data and routing. Troubleshooting Tailwind CSS configuration and deployment with Versel are also discussed.
1. Introduction to Svelte and Agenda
Hi, my name's Scott. I'm a Developer Advocate over at GraphCMS. We are one of the, if not the, only, sorry, the first, sort of, GraphQL based CMSs out there. We're all in on GraphQL and that's pretty much how we deliver our content for our users.
So, let's take a quick look at the agenda. And I know I've not updated the date on these slides. It's showing as So, we're going to create a front end and a back end. We're going to look at some querying data with GraphQL. We're going to take a look at displaying that data in our Svelte project. We'll take a quick look at Svelte directives for managing data on the Svelte file, once it's coming to the component. We'll be looking at rooting in Svelte, along with endpoints. And we'll take a look at deploying to production, if we have enough time.
2. SvelteKit and Project Setup
At the moment, if you're going to create a new project with SvelteKit, it's still in public beta. SvelteKit provides modern web development best practices out of the box, including code splitting and routing. Svelte is like React for vegans, offering HTTP endpoints and file-based routing. Svelte also introduces Visvelte, a superset of HTML, which allows for reactivity within components. The each directive is used for looping around objects. Let's move on to the front end and initialize a Svelte project using the terminal. We'll be using Versell as the deployment target. The project includes a README, package.json, and JS config file for defining paths. We'll also configure the prettier file.
So at the moment if you're going create a new project with SvelteKit, at next, Svelte at next and give it a project name. Once it goes to V1 because SvelteKit is still in public beta, once it goes to V1, at next it will fall away and how anyone builds a project in Svelte. So there's modern web development best practices out of the box with SvelteKit. It's got code splitting built in and fire routing and all the niceness as, you know, we as front end developers are accustomed to.
3. Project Setup and Configuration
I use pnpm for saving disk space. We have our prettier config and git ignore set up. The app HTML file is where the project is built. Svelte has its own head API.
So I use pnpm. You don't have to use pnpm, you can use npm, or yarn or whatever you like. I just like saving in the disk space with pnpm. So I'm just going to wait for that to install, that's done. And if I save this it should also format that for me. Great. So we've got our prettier config, we've got a git ignore with the.env file has been ignored now, which is great. So we've got a static file. I think we're using that for the favicon. Let's take a look here. Yeah, here it is. So we've got our app HTML file here. And this is where the whole project is built into once we hit Svelte build. So it gets built into the Svelte body here, much like you would do with your app ID, which you would do with React. I'm not sure what the convention is for a framework as you have and there's also the head component here. Svelte has its own head API. Anything you use with that gets bundled into this as well.
4. Setting up Front End and Back End
The majority of the work is happening inside the roots folder. We have our index file, which is an index.svelte. Let's run it and see the Hello World in SvelteKit. You can use arguments like dash p for ports and dash o to open it. Now let's set up the back end. If you want to follow along, you can use gitpod.io and the provided repo URL.
Okay. And then this is where the majority of the work is going to be happening inside this roots folder here. We've got our index file here which is an index.svelte. And this is our Hello World. Let's run this and have I got anything else running? Where is my window? We've got our Hello World in SvelteKit.
A couple of other things here is you can put in some arguments which you see I've already done here. So the dash dash p is for the ports. You can also choose to open it. Now it will pop open the tab for us. I'll prefer to have these shortened down just to dash p and dash o to open it. I won't be using that, though. So we've got our front end. Let's set up our back end now.
Hey, Michael. Can I pass the link to the repo? There isn't a repo. I'm just building it from scratch. So if you want to get started quickly, let me go to GitHub here. I've already got that skeleton pre-built. So if you take this, let me put this into the chat here. If you want to follow along and have an environment, you can use something called gitpod. So go to gitpod.io, and then forward slash hash, and then you can see I've already reused it before, and then add in the URL to this repo here. If you enter, it will start spinning up the skeleton for you, so you can follow along from there. So let's just put this in here for everyone. If you want to follow along that way, you can do that. I'm not terribly familiar with Gitpod, so I'm pretty sure it doesn't have PMPM, but I think you can MPM install from here, and install whatever you think for you.
5. Setting up GraphCMS Project
I'll start at the back end now and use a demo account from app.graphcms.com. When you log into your GraphCMS account, you'll see starter projects for blogs. Select 'create project' and pick the London data center. This will provision a new graph CMS project based on the blog template.
Okay, so where was I? I'll start at the back end now, so just sign out on this. Okay, cool. Just gonna use a demo account here. So from app.graphcms.com, if you haven't signed up, now's a good time to just go in. You can authenticate with GitHub, or you can just create an account and authenticate via your email once you get a confirmation sent to you.
So when you log into your GraphCMS account for the first time, you'll see that there's some starter projects here. So we've got one for a blog, and this is just going to scaffold out the schema and all of the models and data types we need for our project to start working on. This has been done in the past for Gatsby with Tailwind. We're just going to be focusing on building a project in SvelteKit.
So I'm just going to say, create project here, and you can give it a description. Keep this checks, if you are just going to be working through it with me. This all includes content on a template already. If you uncheck it, then you'll need to be adding content to it yourself. And for the purposes of this workshop, because of the time constraints we've got, it's good to leave in there. And it's just give you a general idea of how to work with it. If you've got any specific training that you'd like to share, then you can always have a chat with us, and we'll be happy to answer all your questions.
So if that's the general idea of how to work with it, I'm going to pick the London data center, because that's where I'm based, you can pick wherever's closest to you. I'm going to say, Create Project. And this is just going to provision a new graph CMS project for us. And basically off of that, that blog template. So excuse me, while I just get some coffee. This is that blog template. So I'm actually going to create some new papers. So I need to think about what I want to do more. One of the reasons is because I want to get real estate. And that's probably the one of the biggest reasons why I want to go for real estate. But then I want to create a project that I want to see more of in the future.
6. GraphCMS Project Setup
I'm going to create myself a really good allowance with the community plan. It doesn't have to go up to $300 a month. The dashboard for the project has the schema types for author, page, post, and SEO. We'll focus on author, page, and post. We can edit any content in the schema, including relationships. The pre-populated content includes an about page and some posts. Assets in GraphCMS have their own content type. The playground provides auto-populated queries and mutations. We'll be working with posts and retrieving specific fields. Let's move on to the front end of our project.
Okay, so I'm going to create myself, really good allowances with the community plan. And it doesn't have to go up to $300 a month. If you need anything additional, you can get in touch with a sales team and work something out if there's anything additional you need on top of the community plan. But there's a load in here, which should see you very well for quite a while. So anyway, just gonna select that plan. I'm going to invite my teammates later. And here I've got the dashboard for the project.
So over on the left here is where I'm currently. There's the schema. So on here, I've got a schema type for author, page, post, and SEO. For the purposes of this workshop, probably just gonna be focusing on author, page, and post here. SEO isn't really needed for this, but each one of these models here has their own data type, which you can pick off of from the side here. One thing with, let's say, the post here, this slug URL friendly identifier, this is great. This would generate your slug information from other parts of the template, so from here I could have it as the title, let's say, and say author name. And that would generate a unique slug for that. This is a great option, which I would recommend, but this doesn't actually come in this template here so we've just got this slug field, which is a single line of text. Actually, let me see if I can edit this and change this to slug. Awesome. So, this option up here allows you to change the field type. So I'm just gonna change that to slug and then in the validate, oops, sorry, I'm gonna say generate slug from template and I'm gonna say slug here and scroll down here update. Is the screen size okay for everyone? Do you need me to bump it up a bit? Okay. It's a bit crowded now but I'm hoping you can see that better. Okay. So that's our schema and over here, we can edit any content in that schema. So we've got a couple of authors at the moment. So we've got Ronak here, we've got his image, we've got his title, we've got his bio, which is empty and we've got a couple of related posts. Actually let's go back to that on the schema. So if you go to author here, there's this relationship field and if I scroll down the side here, you can pick out a reference and you can connect, you can connect like relationships. So we could say, if it's a one-to-one relationship, so Ronak can only have one post, which doesn't seem right for a blog. We can say, one author can have many posts or many authors can have many posts. Let's just take a quick look at this. So I don't want this to be like me selling the features of graph CMS. This is just our backend, which we're gonna work from. Let's just take a look at the post. Yeah, so this is how you would do it. So you can say two way reference here and we could have, check on that. So one author can have many posts and you can also do it either way. So you can have multiple authors per posts and multiple posts per author. Anyway, moving on. So sorry, we're looking through the content at the moment. So we've got this pre-populated content for us. We've got an about page and then we've got some posts here as well. And we've also got the assets. So assets in GraphCMS is its own content type. So we can add additional fields here if we need to. Just gonna move on from that though. We've got our playground. So when we define that schema, GraphCMS went off and created all of the queries, all of the mutations for us that we're gonna need to work with. So as a first shot, if you do control space, it brings up this, what is it? Intelligence. And I'm going to want to pick out posts. I just hit Control Enter. It's just gonna auto-populate for us. So I'm gonna want something like, hang on let me just find what we're gonna need. Um. Be right back here in a second. Um. All right. So I'm going to have the title of the post. The slug. Dates it was published. Um? And the excerpt of the post. Have any tags relating to it? And the cover image. Then here we can say we want just want the URL for now. So if I. Go into. Uhm? It's going to forgo that data force. So this is one post here. Um, then the next. And then onwards I am and that's what we're going to take a look at getting into the front end of our spoke it project. Now, so let me check the chat.
7. Getting Data from Endpoint with GraphCMS Client
Make sure everyone's OK. Let's go back to the project. I'm going to install some dependencies, including a GraphQL request. Let's take a look at getting some data from our endpoint. We'll define a script module and make a GraphCMS client.
Make sure everyone's OK. Any questions so far from anyone? Uhhm? So everyone could hear me if I see everyone is muted. Uhm I've not got my headphones on so if you need to say anything, like I said before, just drop us a message in the discord maybe or on the zoom chat here and maybe I could answer it, anyway let's go back to the project here.
So what I am going to do. Is install some dependencies so I am pretty sure you don't want to see all of my open applications just let me change this quickly, uhm. Right so two is my main monitor now. Right so to is my main monitor now. I'm going to need to install a couple of dependencies. So I'm going to use a GraphQL request to go off and get information we need so. A GraphQL request I think it's like a HCP wrapper for your GraphQL calls. And this comes pre-packaged with the GraphQL language tag I think, do we need to install it separately? Nope we're in Discord? Close that. Just install this. No I'm going to use my npm. Okay so let's bump up this. Now I've got so many windows open now, where has the chat gone? And... Umm. Umm. Umm. Umm. Umm. Umm. Umm. Umm. Umm. All right, apologies.
All right, sorry. Umm. Umm. I can't find the Zoom call anymore. I apologize. Umm. Umm. Umm. If any of you are trying to reach out. Ha ha. Umm. Can't find the chat. Not that. Or that.olds unless it's not that. Does that not hold. Can't find the chat. Right. Sorry for all that. Sorry about that. Where's he gone. Got it. Got it. So I'm sorry everyone stopped sharing my screen because couldn't work out what was going on. Right. Go back to sharing my screen. And... my code panel backup. Right. Ready to... Right. Let's take a look at getting some data from our end point. So it's going to define... a script module here. So the context module. This is how I can use the... load function from Svogit. So this is... it's not an async function. This is an async function. So I can have this as a load. And this is async. And from here, I'm gonna need the... Actually, I'll just leave it like that for now. And in here, it's where I can make a GraphCMS client. And this is going to be a new GraphQL client.
8. GraphQL Requests and Client Setup
I installed GraphQL requests and GraphQL, but I'm not getting the expected IntelliSense. I'll need to import it manually and define the client URL for my graph CMS project. I'll also create a query to get the posts and pass it into the client. Finally, I'll return the posts as props and display them on the index page.
And I'm pretty sure I installed it. Let's just go back to GraphQL requests and GraphQL. Right. So, I should get the IntelliSense off of that but I'm not. I'm just going to have to import it again. I'm just going to have to import it manually. Jump. The client. And that is not URL for my project. I want to get my URL for my graph CMS project. Turn you on back over to that, which is here. Go down to the project settings here. There's an API access settings. So with this template, these permissions have already been enabled for us. If you're setting up a new project, you're going to need to click on the create permission button here. That will give you the option to just create the defaults, which is what these are. So we can read any models which are in the published stage, and it can read all versions for models. So I'm just going to copy this. I'm going to put that for the URL. There's also a headers config here. I'm just going to leave this empty for now. Just leave that completely. And now I've got my client defined. I can also find a query to use with that. I'm going to want to get out the posts. So, now I'm going to make a query for now. This is going to be the gql tag. You can see that also important there. So in these backticks here, we get a copilot is doing quite a good job here for all posts, ID content created. But I'm just going to disable this because it's getting in the way. And I'm going to go back on over to my project here. And get this query and put that in there. So with that query, I'm going to want to pass it into my client. And I'm going to want to get the posts, which is the posts here. I'm going to await the result from the client by passing in this query here. So that's all good, but I'm going to need to return that information as props. Let's go put in the posts here. So, now I've got that information, which I'm grabbing before the page loads here. I could actually, gonna get off here, and go to my terminal, and run the dev server. You see that it prints out the same object as what we got in the query here. So I can use this now in this page, but I'm gonna need to get these posts into the page, and I can do that with a script tag, and it's export let. So if that looks a bit funky, export let when it's coming in. I'm just gonna say roll with it. That's how you receive props in Svelte. So if I now say, put this into like a pre tag here, and print that out to post we'll go over to project. Whatever that might be, here we go on localhost. So you've got the information displayed to us in our index page. Brilliant, so that looks nice, not, let's work through it and sort of use the, spell each directive or can just loop through stuff and make a card for each one here, let's say. So let me go back over to the chat. Everyone okay, any questions from anyone? Anything needs going over again? Is it going too fast, too slow? Just let me know.
9. Working with Content and Layout in SvelteKit
Okay, all right. So let's work through some of this content now. So for the purposes of this, do you wanna see any styling? Because if I was going to do any styling, I'd probably just use Tailwind just for the speed of which I could go through stuff. And I could probably just copy, paste in some classes and stuff just so it looks a bit more presentable or I'm perfectly happy just to go through it as it is at the moment and work with it like this with no styling. So if you've got any opinions, just shout.
10. Styling with SvelteAdd, Tailwind, and Daisy UI
To make the project more presentable, we can use SvelteAdd to configure Tailwind and Daisy UI. This will allow us to easily add classes and improve the styling. We can install the necessary dependencies and configure Tailwind and Daisy UI in the project. Additionally, we can choose a theme for Daisy UI and use the svelte-each command to work with the data. This will help us organize and display the content in a more structured way.
So that's how you manage it with Svelte. So what we could do is you could use Daisy UI and just scaffold out some styles, briefly. It's not really related to building with SvelteKit and GraphQl, but let's make it a bit more presentable, let's say. So I'm gonna use something called SvelteAdd. SvelteAdd. So SvelteAdd is just a great way to have lots of things configured for your SvelteKit projects. We've got Tailwind here, there's also Bulmer, PostCSS, MDSpecs, SCSS, and lots of other stuff. And it takes care of all the configuration for you.
So I'm just gonna copy this here and use the MPX command. Let's just configure Tailwind just so I can start editing classes so it looks a bit more presentable. I'm also gonna use something called daisy UI actually. Right, how to use? Let's just get this installed as well. There's also a great typography plugin as well. You can use the Tailwind CSS typography and daisy UI. And that really helps for if you've got a lot of content which you don't have a great deal of input on how you would style it within the application. Tailwind CSS typography will just add like a predefined set of styles to any markup within what's being brought back from your endpoint essay. So let's just go over to project now. You see the layout file has got this has been configured from tailwind wait, spell add to tailwind. And it's just importing the app CSS file here, which is being generated by the MPX script. So this just means I can just chuck a load of classes onto various parts of the project now. And it should not look as bad. So let's go ahead and get started. So, we have our main class here, I can just put in just a container. We can put in the max width, MX also here, which is margin left and right also, and just some padding. So now if I go back to my terminal, MPN run dev. I'll need to install the dependencies actually. Sorry, the MPX script will just configure it, and it's going to install the dependencies for you. Right, let's take a look at it now. And where were we? Here. Okay, it's a bit more presentable. Let's get Daisy Ui going as well. So I'm gonna say Daisy Ui and tailwind typography. And it's gonna store these as well. Again, it's dev dependencies. Typography and Daisy Ui. Now I'm just gonna take this plug-ins config here. So what is important is that the CSS typography comes before Daisy Ui. And this into my Tailwind config here, and replace this. Check, make sure everyone's okay. Markin, are you okay now, you still getting a 500? So installation steps for Tailwind. Let's just find them. Right. Okay. It says NPX. Boop. And then, you need to install dependencies once that has run. And I'm also installing a Data UI and the, sorry, probably should've used NPM rather than PMPM there. The term in Typography plugin. And then, I'm just replacing the empty plugins array with that. Cool, cool. Um... Okay, hopefully everyone's okay with that. Let's just go back over to terminal and open the dev server again. Correction? Let's try and make this a bit more... Yeah, yes, yeah, um... So you know it's just a theme that's changed with DaisyUI here. DaisyUI uses... Where has it gone? So I think it's in themes. So it comes with a list of themes and it says the default here is light but it looks like it's the dark. So depending on how you want it to look, you can just go over to the... Yep, to the HTML. Of your Svoltkit project. It's in here. Let's go with, let's just try cupcake for now. That's fine. Okay, Mark you might need to stop and start the dev server again if it's not updated but that's fine. Okay, so with all this data here I'm going to need to work with it. So rather than just dumping it all into this pre-tag, I'm going to use the svelte-each command. So apologies, I'm using like a snippets, I'm using a snippets generator which I think is called svelte-snippets. Let's take a look.
11. Working with Blog Post Data and Routing
I'm using the each expression to iterate over the posts and extract information from the object. I can destructure the title, slug, date, excerpt, tags, and cover image. I've styled the list of blog posts using DayziUI classes to make it more presentable. I've added a link to each post that will display more information when clicked. To get the specific post information, I've created a new query in the GraphQL playground using the post type and passing the slug as a query parameter. Now I can retrieve the information for that post and display it in the template.
Svelte-snippets. I think I'm using this svelte-3-snippets. So it just takes out a bit of the, getting on how to do the syntax for loops and stuff like that. Okay, so we're in this directive here. Let's just say, post.name. No, that should be a ptagsql. Undefined. Right, let's take a look at the pre-json again. Post. Oh, because it's a title, not a name. So this comes in super handy just for validating what's in the data. So I'm using the, each expression here, and for each post in post, I can get out the information from that object. So, if we take a look back here again, so I can get title, slug, date, excerpt, tags, and cover image. I can sort of destructure those straight out into this loop here. So I could say, title, slug, date, excerpt, tags, and cover image. Then inside the loop here I can say title, and then when we have someone click on the list item, isn't it? So, we'll make this an unordered list, and each one of these in here can be a list item. Just make sure list item can have a title. Well, what can we put in here? The excerpts. Get the image in here. That's gonna be, yep, source cover image URL. And should have the, yeah, I should have an old attribute. Name it, title, sorry. Let's take a look at that now. So, I think I've got everything out of the objects here I need, so I'm just gonna comment this out and save that. So we've got the start of our list of blog posts, let's say. So just let me go over to chat, make sure everyone's okay. Everyone okay? How many people we got on still? One, two, three, four, five people. Okay so I want to try and keep it at a pace. I'm a bit conscious of the time. I think we've only got an hour 45 minutes left. So I'm just going to try and get through routing and endpoints in celtkit. So if you're okay with that, we'll try and roll through those, but if there's anything else which isn't clear now, just give me a shout and I'll try and clarify for you. I'm just going to get some water. From now on all with this, how this looks at the moment, let's get in some DayziUI classes and try and make this look a bit more presentable. So you could use a card, I think, so it looks like it puts rounded on the image. I'm pretty sure I should have the image up here, let's say? Better. Okay, so I think this needs a figure. I think this has the classes and let's put in this. And then here. Okay. Okay. So, you try these items as well. We should sort of wreck in, uh, An I tech for the route off that post, this, I say so. Um, so we wanna have more information. Um, say we want to have more information on this, we should be a click on this and go through to our post route, let's say, and display all the information for that. So, um, I shall put this a tag around here. Getting a button Um, well this is an A actually and we have to riff, which can be the slug. So let's put this in some tox and we'll say posts. We have to slug for that post, hover over this link here, which I've given the class of button. I'm not sure how visible it is to everyone, but you can see that this is going off to posts, tech, the questio, we've got CMS, which is what the title is. But if I click on it, I'm going to get a four at four because the page doesn't exist yet. So I'm going to need to create that. So let's go ahead and do that. So let's just go to my VS code here, pop out my file Explorer, require to be posts, and then the slug of the post here. So in routes, our click open the posts file, typing in qchecktilt. So in routes, I'll create a posts folder. Then in here, I'm gonna have the slug and relate to a svelte file. Now in here, you just get the same sort of template for each one we click on. Yep. So now I need to get the information for that specific post into this template here. And to do that, let's go back on over to the GraphQL playground in the GraphCMS project. So this is a query post, so to say. I'm gonna create another query, which is gonna be post, posty, post. And this is gonna need to take a slug, which is gonna get passed to it, as a query parameter. And this is of type string. And then we've got the exclamation mark to say that is required. I'm pretty sure I'm just gonna need exactly this, but just for a specific post. So that's gonna be post rather than posts. And let's get a slug to pass into this query. So I've run all posts.
12. Working with Slug and Endpoints
Let's take this slug here, union types and sortable relations. We're just specifying one post and passing in the where clause to the post. That's what we're going to use for the basis of the post routes. We could create an HTTP get method and call that endpoint from anywhere else in the project.
Let's take this slug here, union types and sortable relations. So let's copy that and go back over to my post query. And then the query variables here, just close this side panel, don't need that. So the query variables here, if I just click on this panel, it pops up. And if I open up some curly braces and hit Ctrl Space, it recognizes the slug as a variable for the query. So I can just hit Ctrl Tab there and then just hard code in this slug for now. Hit Enter. Post needs the argument where of type Post where unique input. All right, yeah. I do apologize. This needs to be where... and more curly boys. The slug is the dollar slug. So I'll just pause there while everyone takes a look at that. I'm gonna grab some water actually. So in here, rather than grabbing all of the posts, we're just specifying one post and passing in the where clause to the post here. Okay, there we go. Just so we could filter out for the specifics on that one post. And that's what we're going to use for the basis of the post routes, I just defined in the project here. So, so in here, it'd be pretty much the same pattern as what we just did for the index.svelt file. So, what I could do is copy all of this again and have like a repeated client in the slug file here. But what I actually like to do is to just abstract away this into its own reusable file. And then I also like to use endpoints as well. So an endpoint in SveltKit, like I said, in the intro slides, you can use HTTP methods. So we could create a HTTP get method and use the same sort of approach as what we've done here. But then we could call that endpoint from anywhere else in the project. So is everyone caught up? Cause I'm just gonna go through this next part now and I'll explain it as I go along. If there's anything you need clarifying, just shout and I'll be happy to explain it a bit more.
13. Creating GraphQL Client and Endpoint
I'm creating a GraphQL client in a separate file and importing it where needed. I've also moved the client configuration to an.env file to avoid hard-coding. By using the $lib shorthand, I can import the client from libGraphQLClient. I've restarted the dev server after adding the.env file. Now I'm extracting the client to its own file for reuse. I'm moving the client code into its own endpoint file to avoid repetition. I've created an index file in the posts folder to define a HTTP get request to the GraphQL endpoint. Now I have a query defined.
So what I'm gonna do is I'm gonna create a lib folder and in here, I'm gonna create a GraphQL client. It's gonna be a JS file and that's pretty much gonna be this. I need to import GraphQL Client. Oh, whoops. I don't know why my import isn't working today. Right, GraphQL request. GraphQL Client, right. And I'm gonna export this. And one other thing while I'm here is I really don't like leaving hard-coded anything in a project. So this should really go into a.env file. So let's just copy that. Let's create a new.env file at the root of our project here. In here, just gonna paste that. It doesn't need the quote marks on it. I'm just gonna call this the vite underscore GraphQL endpoint. So then now, the vite underscore is important. I can use that in my client here. So just up here, just define that. And this is gonna be, is gonna be. How do we do imports invite? Do do do do do do. Well, I know I can do that. I can import any text. Let's see what it looks like on the desktop. Save that, open GraphQL дост, extract, I'm gonna pass my GraphQL endpoint now to my GraphQL client here. Save that. So, this part is completely superfluous. You don't really need to do this, but I'll find that you can swap out the variables as and when you need them. You could just put this sort of straight into here like that. That's just my preferred approach. And so we check the chat, make sure everyone's okay. Okay, cool. Okay, so now I can just import this client anywhere I need it. So let's just do that for this here. Let's go back here. And if I do command space, it lets me auto import it. So if you go back up here, you can see it's importing the client from libGraphQLClient. So the $lib, that was what was defined in the js-config here. So it's just a shorthand for the location of that. So if we hit save on this and go back on over to the project, I believe the dev service to run it is. So that's not working. Oh, this because I've added the.env file and not restarted the dev server. Any configuration changes, I think you need to restart it. So that looks fine. Oh, I was looking at the route which doesn't exist. Right, okay, so it still works, cool. Okay, everyone following along? So I've just extracted out the client here to its own, let's bring this out a bit, to its own file here just so I can reuse it throughout the rest of the project. So I can use that here. But if I've got other areas in the project where I want to list out this information, I don't really want to be repeating this again either. So what I can do is just move this, all that into its own endpoint. So this at the moment is the posts. So in the new posts folder I created here, I can create a new file. And this is gonna be the index. And this is gonna be of a JSON data type. And it's going to be a JS file. So that notation take note of it. So when we go to like posts.json on our client, that's what's going to be returned from the endpoint, the.js is just the language I'm using. You could use T S as well, but for the purposes of this workshop, I'm just going to go with JS. So in our post here, if I go to the index file, I'm going to create a HTTP get to the graph CMS, GraphQL endpoint. Water, hang on. So you can do that in the SpeltKit. And by defining a get. And this is a sync again. And it's going to take a request or response. Yes, thank you Copilot. And in here, I like to do a try catch. And define a query. So that query is just going to be this. Just nick that from there. Put that in here. And now I've got a query defined.
14. Fetching Data from Endpoint
To fetch data from an endpoint in Svelte, you can use the fetch function. This approach is more secure as sensitive credentials are fetched on the server rather than in the client. The code should be placed inside the script context module. The response should be checked for a status of 200 before accessing the data. By abstracting the GraphQL code to an endpoint, you can easily query the data without the need for specific GraphQL code in each component. The endpoint can be accessed using the fetch function and passing the endpoint URL. The response from the endpoint can be returned as props and used in the component. This approach is more secure and follows best practices for fetching data in Svelte.
I want to get out pretty much like what I've done here. Put that in there. And I want to return status 200. Because it's an endpoint. I'm going to put status 200, because it's a good request. And in the body, this method, I'm going to want to put the posts. So I'm not sure if I'm going to need to put these in curly boys. I'll take that once I've finished here, whoops. Take that off. And if you get an error, we want to return, set it to 500, there we go. And a body of error. There we go. So that's like that. So I need to import my client here. That's been important. I need to import it to ql tag as well. It's not going to let me do that. So let's copy this from here and paste it in there. Right, let's go back to the chat. I'm still okay. Oh, now from my client, let's just, again, you'll be able to go to the posts root and if I just say, dot json here, it's, I see this is referencing this index.json.js file here. So if I hit enter, it goes off and this is the information from the end point. So now I can query this, pretty much like you would in, like a browser fetch command. So in my index file here, I could pretty much do away with any sort of graph code or specific stuff here and just use a fetch from the end point. So inside my load function, I can get rid of all of this. I'm still going to keep return the posts because I want to query them from the posts.json endpoint from here. So, I'm gonna say response from under a weight from a fetch on my jsonendpoint, and this is gonna equal a weight, here. post.json. So if the, yeah, if response is okay, I'm just gonna delete that. So if the response is okay, then I'm going to want to get the posts on the jsonresponse, and turn those as props. So now I've just abstracted out all of that information, which was in this context module here, with just a fetch to an endpoint. So if I go back to my index here, I should get exactly the same information. So that's handy for, I know it's using a rest endpoint for GraphQL, and it sort of goes against the ethos of GraphQL, being able to use what you want and where, but for how this project is structured, there's always gonna be a list of posts you wanna grab, and for the index of that one post, like say for this one, we could just go through the exact same thing what we did again, initially, or we could just use an endpoint and pass in the slug. So I prefer this approach because it's a lot more secure. You're fetching from an endpoint rather than fetching from like HTTP in the client. If there are any, let's say sensitive credentials, they are fetched on the server rather than in the client. So if you got like a bearer token or permanent author token, that they can be exposed on the client with the way Vite uses the environmental variables. So this is just a much more secure way to do it. Let's go back over to the chat. Let's go back on over to post.json. So you have a roots post index.json.js file. And then in here, you're defining a Get function and then we'll just Jack in the query from the index page we had, I've just moved it over here now. And using, importing the GraphQL client we created for our, which is in our Lib folder. And then we're also importing the GraphQL language tag from GraphQL requests here, and then we're returning a status 200 and body of posts. So if your code is the same as mine, so let's just copy paste that. So if your code is the same as that, then I'm gonna guess it's, where, well, if it's an invalid URL, I'm just guessing it's not getting the, the URL from the.env file, which it should do. So as long as your endpoint is defined as VITE underscore GraphQL endpoint, and then in your client, you're passing that to your GraphQL client, should be fine. It should be fine. All right. Okay, cool. So Postdoc Jason is working in the browser. However, the request from index.svelt is giving the error. Okay, let's just go back on over to index.svelt. So it should look something like that. So just copy, paste that. That should be inside your script context module. And nothing else has changed in that since we sort of moved over from a, doing it in the client over to an endpoint. Oh, Mer, mer. Well that's, so what does the rest of your module look like? What do you have? I'm guessing it's just, oh, see, this is the trouble I get into when we're just blindly taking what CoPilot offers up. So, that should be response okay, not response okay. So, I'd really do apologize. That was just me blindly following what GitHub CoPilot put out on to the screen. So, God sorry, try it without the exclamation mark. All right. Much better now, I think it's the software, it's actually generated and sorted SX-ON. So, that was Linux X Fighters, the first one who launched the experiment, did their own things uh, uh, in fact they weren't so bad because most of their pages are in greaseproof. So they're in the recent iPhone, so they don't have to worry about so much handwriting or voice, Jason, right? Sorry, it's, it's a me, not a you thing, sorry. Inventory post, not Jason, so have I done that completely wrong? I mean, that should be fine. What am I doing wrong here? Oh my, Oh my God. I'm so sorry, yeah.
15. Working with Slug and Endpoints
The load function takes, because this isn't in the browser, this is a good learning point. We don't actually have the fetch API. So that needs to be imported from the svelte kit. Let's just stop and start that again. Unrecoverable error in index. Oh, I've done. End tech, so in our load, if edge, who are waiting the fetch from our endpoint, that's okay. Let's put this back into some VecTyps here. We want to use the query we defined earlier in our Graph C and S project. We're going to pass this slug variable to this query onto an endpoint. We're going to have the slug. Let's take a look at the page. So that's the information on our endpoint for that specific post. I've created a slug.json.js file and this takes in an incoming slug parameter, and then I'm using that along with a query which takes in a slug parameter and then passing it into the graph12 client. Let me check the chat, make sure everyone's okay.
The load function takes, because this isn't in the browser, this is a good learning point, right, because this script context module isn't in the browser. We don't actually have the fetch API. So that needs to be imported from the svelte kit has its own sort of fetch wrapper. So if we try that, and try, refresh. But it's not showing anything. No, I mean, that should be fine, yeah? Let's just stop and start that again. Check out the console. Unrecoverable error in index. Oh, I've done. End tech, so in our load, if edge, who are waiting the fetch from our endpoint, that's okay. So if you go here, just print this out. I'll just put response. That will give it a... That looks fine. All right. Is it because I've wrapped it in, wrapped it too many times in curly-boys? That looks okay? There we go. I've destructured it one too many times, I think, on the end point here. Where is it? So I'm destructuring it here and then... That's inside the post body, so that should be fine. But yeah, I was trying to do it on here as well, but I didn't need to. So, I do apologise for the confusion. So we check the chat. It's working out. Okay, cool. Right, so, let's put this back into some VecTyps here. Right, for our route now, so for each post. This looks so junk, I'm sorry. So for each post we want to go on here, we want to use the query we defined earlier in our Graph C and S project, which is here. So we want to use something like this. I've just got to take my headphones off. Can't hear myself talk. So we're going to use something like this, we're going to pass this slug variable to this query onto an endpoint. So let's go and look at this. That's going to look a lot like this one here, but instead of like index.json, we're going to have the slug. So how it's done with the page routes in SA, it's got to be the same sort of file format. So if we say new file here, and this is going to be based off of the slug, and this is going to be a.json.js file again, and really we could just jack most of this information from here and pop that in here. So that's repeated code, but this is going to be the query from our projects here. So just a copy of that. And now, and hit save. Okay, I want variables for the slug variable here. So to get that, we can get the information out of the request.body. So let's just console log that for now. Yeah, params. So let's say this slug. So we should be a say now is this is Jason at the query for that slug. Okay, slug must be defined. We haven't got it defined yet, but we should have had it logged out here. So we've got a slug technical SEO graph CMS. So I can take that out of the request params here. Just to structure it straight out of the params to say slug. It's gonna equal the request.params. I can use that slug as a variable to pass into the client here. So I could just do like that. Let's take a look at the page. If that's gonna refresh for us. So that's empty. So if I've done the same thing with structuring out the posts, when I didn't need to. I know, cause I'm just grabbing a post this time, not posts. Let's just replace that, take another look. There we go. So that's the information on our endpoint for that specific post. So, over in the project now, hang on, I'll just hang about on here just so everyone can get an idea of what's going on. I love you used the dancing man emoji. Right, so let's just review here. Hang on, let's make this a bit bigger. Right, so I mean, I've created a slug.json.js file and this takes in an incoming slug parameter, and then I'm using that along with a query which takes in a slug parameter and then passing it into the graph12 client. So what I could do with this rather than just have it in there like that, lets make another variable with objects here and that give equal slug, and just pass in the variables. And let's go back over to the endpoint. That's working, there we go. All right, let me check the chat, make sure everyone's okay.
16. Displaying Post Information and Styling
To display the information for a post, we can use the same pattern as the post slug endpoint. We can fetch the post using the slug parameter from the page params. We can then render the post content using the post.content.html property. The prose class from Tailwind CSS typography can be used to style the content. We have covered endpoints, routing, and querying data from our endpoint. Now we can make the page look nice by adding daisy wire elements, a header, and a footer. We can also use information from the endpoint to create a dynamic nav bar. If Tailwind is not working, ensure that the Pros class is configured in the Tailwind CSS file by adding the necessary plugins.
So now for what I've done with this post slug endpoint, I can use the same pattern. That's what I did in the index file here. I'm just gonna take all of that, put it into here and just change. This is gonna be, this is gonna fetch the post, not dot JSON. This is gonna be a forward slash slug. Slug dot JSON, which reflects this. I'm gonna need to get a slug from somewhere. And it's gonna come from the page params. I'm just gonna destructure these out, actually. And I can get the slug from the params object. Get the slug. This is gonna be posts. I want this prop to be a post, this post. And this is post. I'm just gonna bring this back up and get rid of all this. So now for go back on over to the browser and just get rid of this.json. There we go. So I can start working with this to display the information for that post. I'm gonna need a bit more data than we'll put in here the excerpt. I'm actually gonna need the post as well. So let's let me go over to here. Let's go to the schema and post. Just follow what's called content. So I'm gonna need content as well. Let's go back to the API Playground, post. Let's just put this out to tags. We'll put content. I think that was a rich text field. So in here I can say raw HTML or markdown. I think I will say, let's say HTML for now and save that. I need that. That's putting it in my end point here. Cool. Now I can start working on sort of rendering out some of this information here. Let's just go to the chat, make sure everyone's okay. All right, so just give me a sec, hang on. Oh, there we go. Sorry, I turned some lights on, I can't see anything. Where were we? Well, it's to start rendering out some information for this post, I guess. So we're going to have, let's put in a cover image. I'm just going to start pasting in some markup for this actually. Let's put in an article tab. And inside the article tag here, I could just get the post.content. What was it called? Post.content.html. If I say that and I go to our page here, here we got P tags, with Socket you can use the at HTML director here. And it'll come over your html into proper format of HTML, but you should be wary that you either trust your, the source of that HTML, or you sanitize it before displaying it. We trust the source because we put it there. So what else can we put into, we could use we could use prose class here as well, where they look a lot more presentable. So this is the thing with, where can I put this? Let's put it over to there. Nope, not that. Oh yeah. Oh, I couldn't move it because it was in full screen. Okay. Yeah, so the pro tag here just basically adds all the classes we need to this content. So otherwise we'd probably have to do something like creating a big, like CSS class file just to take care of all of the possibilities of how we want the various HTML elements coming from the CMS format. So we have that Tailwind, God what's it called? Tailwind, Tailwind CSS typeography that takes care of a lot of that for us. Let's format it a lot nicer. Okay. So we've covered end points. We've covered rooting and we've covered querying data from our endpoint. I know that this is like really rudimentary. Let's go back to the homepage here. We've got a way to visit the, each individual post which has been rooted for us with SvelteKit. Yeah, I mean, we could go ahead and make this look pretty or we could go over some other concepts before we finish. I think we've got just under an hour now. So let's have a chat, make sure everyone's cool. Right, so is there anything anyone in the group wants reiterating, going over again, or anything else? So what I could do is we could just quickly make it look nice, put in some daisy wire elements and like a header and a footer and we could use some of the information from the endpoint to render out a dynamic nav bar, let's say, and put some information in there. Antwin, Tailwind is not working. I'm not sure, when you say Tailwind is not working, does that mean the Pros class? Do you have it configured in your Tailwind CSS file? So, over in the Tailwind, sorry, the Tailwind CSS, Tailwind config, you need to have plugins configured here. I think I posted those into the chat earlier, but I'll put them in here now.
17. Troubleshooting Tailwind CSS Configuration
Did you install Tailwind CSS Typerography in your package.json file? In the layout file, make sure to import your app.css. If you're experiencing issues with Tailwind, try running 'Svelte Add Tailwind' to configure everything. Check the configuration and preprocess settings to ensure everything is set up correctly.
Did you install the, okay. You've got Tailwind CSS Typerography in your package.json file? Ooh. I'm sorry. So I'll just wait in the, both plugins are installed okay. In the layout file, where is it? Here it is. So you need to import your app.css. That should have been done when the spell ad configured it for the project, might also be an idea to see if there is two slots in here as well. If you've already got a slot defined, sometimes it just brings another slot in there. So might as well check that as well.
Hello. Okay. So over in your Slug dot spell, you're saying the pros class isn't being applied? Let's just take a quick look at this in, look in here. So if I click on one of these and I inspect, let's just dock this over to the side here. You see it. If you don't see the pros class being applied, then, I'm not sure if it's a tailwind config issue, or what. I don't know. If you've got all that stuff installed then, there should be no issues with it working really. Stop and start the dev server maybe.
Alright. So, Svelte add Terwind. We just run that to configure the project. So, that'll just add in. Let's have a look. What it adds. So, Svelte or Terwind will add your config, they'll add a post CSS.config.cjs file. I think it will put in a pre process into Svelte config.js. I'm certain of that. And then in your layout file, it should import the app.css, which is this. I like to take a quick look at that. I need to take a quick comfort break, so I'll be back shortly.
Okay. Thanks, Hugo. Antoine, are you still having issues with Tailwind? Yeah, you should just better use the Svelte Add, like you said, Svelte Add Tailwind and that should configure everything for you, then you can add in DaisyUI and the Tailwind CSS topography plugin afterwards. So, that was the correct order. I don't think that's an issue if you do it the other way around, to be honest. And that should be it. So, I mean the layout.svelte file is where you import your, the CSS file, which is here. And the only other thing I could think of is just how it's configured. So, you say you've got your plugins configured. That's fine. Svelteconfig, SvelteAd should have added the preprocess here, I think, with Post CSS. And your preprocessor up here. Should, if you said you've got a Post CSS config file, that's fine. I can't think of anywhere else there would be an issue.
18. Working with GraphQL Endpoints
We've queried for information from the GraphQL endpoint directly in our index file using the Context module. We've also abstracted the client into its own file for reusability. Additionally, we've defined an endpoint in SvelteKit to retrieve data from the GraphQL endpoint. This endpoint allows us to specify the return type, such as JSON or XML. By using the fetch method, we can call the endpoint and return the data as props to the component or page. We can then loop through the data and render it on the page. The slug.json file shows how we retrieve the slug from the page params and use it in the GraphQL query. We've also abstracted this process into another endpoint for reusability.
19. Debugging and Deployment
We're just structuring out the post from the result of the request from the query with that variable being passed in. And we're just getting the post returned as the body of that HTTP method. So, every time someone posts into the chat, for some reason it scrolls right to the top of the chat and I've got to scroll back down to the bottom again.
We're just structuring out the post from the result of the request from the query with that variable being passed in. And we're just getting the post returned as the body of that HTTP method. So, every time someone posts into the chat, for some reason it scrolls right to the top of the chat and I've got to scroll back down to the bottom again. So, Mark, you're getting a 404. It's just waiting for your own message. So, can you just do, can you just do, yeah, like I've done here, just add. So, can, let's go back to the actual files. Can I read properly cover image of null? Well, rather than me trying to debug that now. So, from your index plugin, you can pick out a route here and it will display the information. If you can do that, then just try takcon.json to the end, and that should work. So, if that doesn't work, then I can't see how this should be working because it's getting the information from the end point. So, if you just give us a bit more information, I could try and help you debug it. Doesn't work without.json. So, it's not working at all. So, let's take a look at your slug.json file. I just, I just post it into the chat. That should see, I think, if you put that into your slug.json.js file. I'm just gonna go back to my slug.svelt file here. And I'm just gonna dump out the contents of this post file. And debug that issue for the cover image. So the cover image is here, okay? And it should have a URL. So post.coverimage.URL, don't know what you're complaining about. Okay, seems fine now. Oh, good! Okay, so just pause here a sec for Markin, make sure he's all right. And once we've done that, we'll just cover deployment real quick, and I think we'll wrap up. So I'm going to use Vercel, and a really good way to get started with Vercel, if you don't have it installed already, oops, what have I done there? Cause you can install it as a, like, a global NPM package, but if you don't have it installed, you can just use, I think it's npx-vercel. And that will set up the CLI for you straight away. But let's just wait for mark-in, make sure it's all right. Still errors, so if it's not the, if it's not the end point mark-in, I'm guessing it's how you call it out to it? So what I'll do is I'll just deploy this and I will push this code up to GitHub and let's do it now actually, just so I can share in the chat and everyone's got a link to it. So let's deploy it first, so I'm going to use npx-yself. This is going to ask me a setup and deploy, GraphQL Galaxy Workshop, I'm just going to say yes. I'm going to post it onto my account. I'm not going to link it to an existing project, I'm going to give it that name and it's in the roots. It's going to say no, the default here. So this is going to go off and build to Vercel, but this isn't going to do much on Vercel because the environment variable is not on there. So if I go to vercel.com and this project should show up here GraphQL Galaxy Workshop, then go into deployments and I click on this. And I click on this. It shouldn't take long to build. I need to wait for this to be installed. Or if I'm doing it from home. So while we have this large pause, waiting for this to build, I could go off and publish this to GitHub. It looks like it's done its thing and I am partly confused as to why it's showing the content on here. Cause I haven't defined the end point. How does it know where this is coming from? I haven't defined the end point. How does it know where this is coming from? Network, and xhr. Yes. So let's just fetch from here. Oh wait, the endpoint's there. How is the endpoint there? So if we go back to my code, I'm pretty sure the endpoint isn't detailed anywhere apart from in the.env file. Ah, it's pushed the.env file up as well. But that should be ignored in Git, right? Well, that's kind of a right. So what I'm going to do is um, like a project for this on GitHub. And say new repository, and I'm going to give it the name of project, which is GraphQL Galaxy Workshop 2021, copy that, and paste it in there. and say create repository, and just copy this, into the terminal here, Let's kill that, Okay, so, I'm gonna need to get in it, Now can add that remote, give it branch main, not master, There we go. Rift name Riftshead, Maine, not found. Huh, I guess I'm going to need to commit some stuff to it as well. So let's go over to my completion of commits here and say new features now, we're gonna say introduce new features, I say init. All right, let's try that again. Okay, and push this. So can we go to GitHub, I can refresh this page and there's no.env file, which is fantastic. So now if I go back on over to Vercel here and go over to the project and say connect to Git repository, and it's GitHub and this is the GraphQL Galaxy Workshop, and say connect. So any pushes now to that repository should be built automatically with Vercel here. So we've already got this first one in. Now I'm curious as to if I make a change now, say it's going over to the ReadMe, I'd just change this to, there we go. So if I say update ReadMe, and try that. So if we go back over to Versel now, should be deployed on push, oh, I need to push those myself. So that's pushing up to Versel now. So if I check this, I should have it built in, here we go. So now I'm going to say this doesn't build because the API endpoint isn't here. So we can quickly go over to configure in the environment variables.
20. Deploying a Subfolder and Defining Endpoints
Can Versel deploy a subfolder inside a selected repo? Yes, it can, but it depends on the contents of the folder. The folder needs to have a package.json file. Previously, Versel allowed pushing anything to the platform, but it has become more selective now. You can navigate to a subfolder and deploy it. When deploying from a local environment, Versel pushes everything regardless of the ignore file. To define the endpoint, you need to add the Vite variable from the .env file in the settings. After redeploying, the missing variables can be loaded. Visit the Validation Settings page to see the snapshot colors when shoes are added to the app. In the components section, you can find the latest data, screenshots, and number of feet. Feel free to ask any questions about the repository.
I don't think we can wrap up. Let me check the chat. Marken is still struggling. So here we go, here's the repo which we've all been working on together Marken. So you can take a look at that. Can Versel deploy a subfolder inside a selected repo? Yes. But it depends on what's in that folder. So if it's, I think it needs to have a package.json. Not sure. It used to be that he could just push anything. You could just say, V-C or Versel and just push anything off you needed. But I think it's got a bit more selective now when they change platforms. A while back now, a couple of years ago, you could just use it as like a CDM just push everything off it. But I don't think it's as flexible now. But yes, you can navigate to a sub folder and say, Versel and it will deploy that sub folder.
So, everyone got the workshop link? Let's just go back on over to Versel. So I'm saying that there should be an error. Yay, okay good. Right, so this is because the endpoint hasn't been defined. So I'm guessing when you do Versel from locally, it just pushes everything regardless of whether you want to get to ignore it or not. So, in my settings here, if I go over to environment variables, I'm going to need to add that Vite variable which is in my.env file. I'm going to need to have this as the name and then URL as the value, so if I say add, and go back over to the deployments now and click on this, but it's not really failed, but it's not using the URL, and if I say redeploy I could have included the build cache there coz everything was fine apart from the missing variables, so I'm guessing if I refresh this we should get some logs, maybe not, there we go. If I do that I should be able to bring back some of the variables and load them to me. Cool, super quick. Now if you go to visit this page, the Validation Settings, you will be able to see the snapshot colors when the shoes are added to the app. Again, you go to components and here you can see all the latest ones from堡data, screen shots, number of feet, I'm going to leave a couple of minutes for chat, specifically the repository you created there.