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. Making our code examples look nice6. Adding error pagesModule 5 - Adding the Database
1. What is a Migration?2. Our first migration: articles 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. Introduction to authentication4. Our second migration: Users Table5. Storing passwords securely6. Authenticating users Part One7. Authenticating users Part Two8. Remember me/Forget me9. Managing posts using a hypermedia API - Part One10. Managing posts using a hypermedia API - Part Two11. Managing posts using a hypermedia API - Part Three12. Managing posts using a hypermedia API - Part Four13. Implementing CRUD For Articles - Part One14. Implementing CRUD For Articles - Part Two15. Implementing CRUD For Articles - Part Three16. Implementing CRUD For Articles - Part Four17. Flashing Ourselves/Providing Visual Feedback - Part One18. Flashing Ourselves/Providing Visual Feedback - Part Two19. Flashing Ourselves/Providing Visual Feedback - Part ThreeModule 7 - Adding Subscribers
1. What are the minimum requirements?2. Expanding the database: Tokens & Subscribers3. Creating the token and subscriber models - Part One4. Creating the token and subscriber models - Part Two5. Creating the subscription form6. Saving and verifying subscribers - Part One7. Saving and verifying subscribers - Part Two8. Saving and verifying subscribers - Part Three9. Emails and Clients - Part One10. Emails and Clients - Part Two11. Emails and Clients - Part Three12. Our fifth migration: Tokens Table13. Email validation view14. Email validation tokens15. Sending validation emails with SES16. Making it all come togetherAdding Subscribers
Emails and Clients - Part One
Summary
Coming soon.
Transcript
All right. So to deal with emails and email clients, we need two elements. We need the actual email and the client. Right. And we're going to be tackling the client in a minute. It's actually not that interesting. It's more interesting how we actually generate the email itself. Now, when you send out emails right now, you typically want to send two versions. You want to send an HTML version and a text version. The HTML version we can make look a lot prettier. We can add styling. We can make it match our color theme. We can do a lot of things with our HTML emails. But not all email clients, email receivers, like the client that the user is actually receiving the email in, maybe doesn't support it. Maybe have it turned off. So it's good practice to also send a text version. Now, you can do this in different kind of ways. You can write both the HTML and the text version, or you can use the approach that we are going to take is to first just create the HTML one and then pass it into a text version. It will look a little less pretty. You will have better results by creating the text version yourself by hand, but that also is extra work. You might mess up. So I like to at least as the default, take whatever HTML version we have and turn it into a text version. And to do this, we need to add two dependencies. We need to add this HTML to text. And we need to add this pre-mailer package here. So let's add those. And then we're going to jump in here and create a new directory called emails, where we are going to create a new file called email. Let's try again. Email.go, package emails. And here we want to have two types. We want to have an HTML type, type string, and we want to have a type text that's also a string. Then we want to create a method on these. So I'm going to create a method on the HTML here that's called string, returns a string. So it's literally just return string. Come on, string. There we go. And this just makes it a little bit easier to work with later on. So we also need text and return that. Great. Now, the way that we embed our articles into the binary is going to be very similar to how we're going to ship our emails because we're going to be using Temple. So we already have to generate the content. We just need to provide it with some variables like the confirmation link or the unsubscribe link or whatever we might need. So we're going to say go embed everything with underscore temple.go in the name. We're going to call it HTML templates, which is embed.fs. Then we're just going to create an interface here called template handler. So we can just easily make sure that all of our emails can actually go through this process that we're about to create. So to be a template handler, we need to have implemented the generate method, which just takes in the context and it returns us HTML text or an error. Then we're going to create another helper method here called process email that will take in the context and a temple component temple components go and it will return a string string or an error. So the way this thing works is that we take and we render the temple component into a bytes.buffer that we're going to call HTML. So we're going to say if error temple render because we can just provide it with context and then an IO writer so we can write it basically to whatever we want, right? As long as it fulfilled that interface, the IO writer interface, which our HTML or bytes.buffer does. And again, if error is not equal to nil, we just return two empty strings and the error. Then let's say pre mailer error. Let's just call it pre mail here and say pre mailer new pre mailer from string HTML string and pre mailer options, new options. Do we have new options? We have new options. If there's no error or if error is not nil, again, return the error, handle it further up. Then let's inline the HTML. So pre mailer pre mail trans form. And again, let's just grab the error handling here. Let's say plain text error and then we can say HTML to text from string. We pass it to inline HTML. We say HTML to text dot options and we want to add pretty tables to false. It gives better results. I found again, return the error if there are any. And if not, then we return the inline HTML, the plain text and nil. All right, and we need a parentheses here. So this process email function uses the two packages that we imported, right? It takes a document and create a go query document so we can create this pre mailer instance. We transform it and then we use that to convert it into a text version that will most of the time look quite decent enough at least that we don't need to worry about it. So this is the main meat of our email processing. Next up, we need to create a base email because we need to use inline styles. We cannot use regular styling or let's say quote unquote normal styling. We can't just have a style sheet that we refer to. We can't use Tailwind. So next step is to create some base template or base component that we can extend to actually create our emails.