Module 1 - Introduction
1. Welcome to the course2. Why Go3. Why start and build a blog?4. What about React/Vue/Angular?5. Getting setup and source filesModule 2 - Tech Stack Walkthrough
1. Introduction to Golang Part 12. Introduction to Golang Part 23. Introduction to Golang Part 34. Structuring Golang Applications5. Templating with Templ6. Just enough interactivity with HTMX7. Getting started with postgres8. Servers, routers and endpointsModule 3 - Creating the MVP
1. What are the minimal requirements?2. Doing some initial plumbing3. Embedding static assets4. Creating our first views5. Tailwind & Utility-first CSS6. Styling the Landing Page7. Styling the Article PageModule 4 - Managing Content
1. Choose your own adventure2. Writing in Markdown3. Parsing Markdown to HTML4. Frontmatter and Meta Information5. Serving the Content6. Making our Code examples look niceModule 5 - Adding the Database
1. What is a Migration?2. Our first Migration: Posts Table3. Creating the Database Layer4. Showing the Latest Posts5. Slugs and Human Readable URLsModule 6 - Managing the Blog
1. What are the minimum requirements?2. A new layout approaches3. Creating a rough outline4. Our second migration: Users Table5. Introduction to authentication6. Storing passwords securely7. Authenticating users8. Remember me9. Managing posts using a hypermedia API10. Our third migration: Altering Posts Table11. Only show posts marked readyModule 7 - Adding Subscribers
1. What are the minimum requirements?2. Our fourth migration: Subscribers Table3. Creating the subscription form4. Adding some interactivity with HTMX5. Saving new subscribers in the database6. Verifying subscriber emails7. Our fifth migration: Tokens Table8. Email validation view9. Email validation tokens10. Sending validation emails with SES11. Making it all come togetherCreating the MVP
Doing some initial plumbing
Summary
In this video, I demonstrate how to set up a basic Golang application structure for an MVP. I initialize a Go module and add dependencies like Echo and Temple. I create packages for views, controllers, routes, and server, along with a main.go file. I walk through creating a base template, basic controllers for home and articles, route management, and server initialization. The goal is to establish a clean, modular foundation for our application that can be easily expanded.
Transcript
We're almost ready to start building. We have the background knowledge. We have a basic outline of our task, that's why we're limited in scope. But before we begin, we need to do some plumbing. Let's take what we learned in the episode about structuring Golang applications and create a base from which we can build our MVP. Let's start by initializing a Go module in an empty directory. We are going to call this block, and then we're going to add some dependencies. We need echo and we need temple. So let that download. Great. Next up, we only need four packages for now. We need a views package, a controllers slash handler package, a routes package, a server package, and then finally a go.mod file where everything comes together. So let's go ahead and create those directories. Controllers and then routes and then server. Finally, our main.go file. And there we go. Let's begin in our views package, where for now, I just want to create our base template. That's going to go into package views. That is just going to consist of a very basic HTML file where nothing really new here, right? We are just creating our base template that we can wrap all the other pages in as we've seen earlier using this children attribute here. For our handlers, we also don't really need a lot of structure. So let me just create our controllers, controller.go. Package controllers. And we want to have a home controller that takes in this echo context and returns us an error. And for now, it's just going to return nil. We can copy this and also create our article controller. And it seems like we might need to jump out and run go mod tidy. Let's see if that fixes the error. It does. Next up is our routes. And like all the other things, this is also going to be very simple. It's just going to go to packet routes where we're going to create a route struct. And this route struct will hold an echo instance. Echo instance. And to create this, we're going to create a function called new routes. This is a very common pattern you see a lot in Go. So we just need the instance that we can call echo new like this. And then we just wrap it in the route struct. There we go. We will eventually have to add our controllers to this route struct so that we can direct requests to the right controller. And for that, I like to split it up into separate files. So let's say we have the home page that might have different controllers or we have the article page that might have different controllers. And it's nice to have that separated out. But we also need to make sure that our routes are loaded in before we initialize the server. Right. So to do that, we're going to create a load function. And the load function is simply just going to return the echo instance so that we can provide that to our server when we initialize it. And this one is simply just going to be returning like this. And then here we will set up routes for different pages. So this simply just allows us to more easily split up our routes and have a better overview of what routes exist in our application. For our server, we also want to create a struct. So let's create it in PacketServer. It's going to be server struct, which is just going to be having three dependencies or three attributes called host and host. And then the routes we set up earlier. And we're not going to point it to our route struct. We're just going to point it to the echo instance because once we get to starting the server, all the routes will be ready and we just need to provide it with that instance. So as before, we also create a new server struct. It's going to take in host and host. And then we're going to set up the routes. It's going to take in host and port and routes. And return our server. So we can say host, port and routes. Right. Now, once we get to the point, we also need to start our server. And to do that, we're going to add a start function to our server objects, our server struct, which is going to be looking a little bit like this, where we create a server struct from the HTTP package. We put in the address that the server is going to be live on. And then we provide our routes, which is the echo instance, which is going to go into the handler. Then we set some timeouts here, a read timeout and a write timeout, like we spoke about in early episodes so that we can cancel requests that take too long. And then finally, we start the server with listen and serve. And then we panic if anything goes wrong. We want to panic here because this is the entry point into the application. So we want to know early on if something is wrong. A little bit later, we will do what is known as graceful shutdowns. Whenever we deploy a new version of our application, we might have some requests that are actually in flight. And if we just kill the server and put up a new one, those requests will just get dropped. So later on, we will set up so we can gracefully shut it down, which just means that we give it some time to finish its work, but it's not going to accept new requests. And we can do what is called like a blue-green deployment so that our users hopefully will not recognize that we are releasing new versions of our application. And finally, we can make all of this come together in our main.go file, right? So we just need a function main. I'm going to set up our routes with our new routes function we created. Then we're going to create the server. New server, going to be on 000 and then listening on port 8080. And then we can say route load. So we have a route load into our server because this just returns the echo instance. And with that, we are ready to call serve.start. If we go out now and say go run main.go, you can see that we have starting the server on host 000 port 8080.