Independent Consultant
Course Description
Code a high-performance fullstack app from scratch! Skip the framework and create a modern Vanilla JavaScript app with web components, dynamic client-side routing, View Transitions, and data filtering and sorting. Build a rock-solid backend JSON API with Go, complete with authentication, logging, and a Postgres database layer. Learn to build robust applications, with higher performance and fewer dependencies, in Vanilla JS and Go!
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseLearn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 19 minutes
- Maximiliano introduces the course by discussing core topics and prerequisites, including a basic knowledge of JavaScript, HTML, CSS, Go, and SQL. He also provides the workshop materials, including the project code and dataset.
- Maximiliano introduces the course project, which will include features such as filtering, searching, marking movies as favorites, and user account functionality. The project will also include user registration, authentication, and the ability to mark movies as favorites and add them to a watchlist.
Building a Backend with Go
Section Duration: 1 hour, 41 minutes
- Maximiliano demonstrates how to create a new Go module using the "go mod init" command and explains the basic structure of a Go project. Additionally, Maximiliano discusses the process of adding external dependencies to the project using the go.mod file and the "go get" command.
- Maximiliano demonstrates how to set up the server using the HTTP package and the ListenAndServe function. He also shows how to handle different routes using the FileServer function, which serves files from a specified directory.
- Maximiliano explains the architecture of the app, including the user interface, frontend, transport, backend, and database. He also introduces the Air tool for automatically restarting the server when files are changed, and mentions the use of PG for PostgreSQL.
- Maximiliano discusses two options for creating a logger: using a cloud-based provider or creating a custom logging system that writes to a file. He demonstrates how to create a logger package in Go and explains the design pattern of returning two values (object and error) in functions that may trigger an error. Maximiliano then shows how to initialize the logger in the main.go file and use it to log messages and errors.
- Maximiliano walks through building the project models, which are the structures for each entity in the project, such as movies, genres, actors, and users. He also explains how pointers indicate optional fields in the models.
- Maximiliano demonstrates how to create a handler for a RESTful API in Go. He creates a method within the movie handler structure to handle the API request for retrieving the top movies. He also demonstrates how to set the content type header to JSON and encode the movie data into JSON format.
- Maximiliano explains that when using an "if" statement with multiple conditions, only the last condition is considered. He suggests using the HTTP package to handle errors and send appropriate HTTP error codes. He also discusses the need to register the handler with the server and explains how to create a new instance of a structure in Go.
- Maximiliano walks through installing a tool called "Air" that provides live reload for Go apps. He demonstrates how to install the tool using the command line and explains that it automatically rebuilds and runs the server whenever changes are made to the Go files.
- Maximiliano walks through creating a `writeJSONResponse` function to handle the common code for setting the content type, encoding data into JSON, and handling errors. He demonstrates how to define this function and use it in the `getTopMovies` and `getRandomMovies` handlers.
Postgres Database Layer
Section Duration: 1 hour, 19 minutes
- Maximiliano discusses the database table structure, including entities and relationships, and emphasizes the need for normalization in a SQL-based database. He provides a step-by-step guide on setting up a PostgreSQL server using aiven.io and also explains how to populate the database using an import script or by importing a SQL dump file.
- Maximiliano explains that creating an interface allows for future-proofing the backend project, as it allows for easy database changes. He demonstrates the creation of an interface called "movie storage" with functions such as getTopMovies, getRandomMovies, getMovieByID, and searchMoviesByName.
- Maximiliano demonstrates how to store the connection string, retrieve the connection string, and open the database. He also demonstrates how to handle the naming mismatch between Go properties and the database field names by adding metadata to the models.
- Maximiliano demonstrates how to import the Postgres database driver and explains that it is necessary to connect to the database. He demonstrates creating the movie repository, including how it creates a new instance of the repository, implements the interface methods, and handles SQL queries.
- Maximiliano discusses how handlers handle HTTP requests and responses, while repositories handle communication with the database. He also demonstrates how to pass the repository and logger to the handler using an initializer function.
- Maximiliano demonstrates how to debug and fix errors in a Go backend application. He identifies an internal error in the handler and traces it back to a problem in the movie repository. He also implements a handler for random movies using similar logic.
- Maximiliano adds more database queries, such as getting a movie by ID, searching movies by name with optional filters, getting all genres, and fetching movie relations like actors and keywords. He also tests the logger functionality by logging an error message.
- Maximiliano finishes the handlers, which include functions such as getting movies by ID, getting all genres, and searching for movies. Once the handlers are completed, the URLs need to be registered so that the server can respond to the corresponding requests.
Client-Side Application with Vanilla JS
Section Duration: 2 hours, 12 minutes
- Maximiliano walks through how to set up the HTML structure for the course web app, including linking CSS and a web manifest file. He also builds the header section of the app, including a logo, navigation bar, and search input.
- Maximiliano demonstrates creating a global app object with a search function that prevents the browser from reloading the form. He also explains how to connect the JavaScript file to the HTML file using ECMAScript modules and the defer attribute for improved performance.
- Maximiliano explains how to create an API service in JavaScript using the fetch API. He demonstrates how to make API calls to a backend server and retrieve data using async/await and the fetch.json method. He also discusses the use of try/catch blocks to handle errors and suggests encapsulating the API service to prevent exposing it in the console or to unauthorized users.
- Maximiliano demonstrates how to create a Web Component by defining a template using the HTML template element and explains that the template is not rendered by default and needs to be used with JavaScript.
- Maximiliano demonstrates creating the homepage component. He extends the class from "HTMLElement", uses the "connectedCallback" method to execute code, retrieves the template from the DOM, and appends it to the component.
- Maximiliano explains how to dynamically render content in the web component. He demonstrates how to create a render function and call it within the connectedCallback method. He also uses the API module to fetch and display the top movies and random movies.
- Maximiliano demonstrates how to create the movieItem component, pass the movie as a property, and render the movie details using HTML and template strings. He also mentions the need to implement pagination or infinite scrolling for large datasets and discusses the importance of server-side rendering for SEO purposes.
- Maximiliano provides an overview of the course project so far, highlighting components like app.js for client-side interaction, API.js for backend requests, main.go for server setup, handlers for HTTP requests, and models and repositories for database interactions.
- Maximiliano discusses creating an animated loading component using CSS animations instead of traditional loading spinners or progress bars to indicate loading times in web applications. He also demonstrates how to create an "animated loading" component with CSS animations for a wave effect.
- Maximiliano explains the process of creating a web component for a movie details page, including registering the component, loading CSS files, using Shadow DOM for styling, fetching movie data from an API, error handling for non-existent movie IDs, and populating HTML content dynamically.
- Maximiliano demonstrates how to create a web component for embedding YouTube videos dynamically by listening for attribute changes using JavaScript. He also explains the process of defining the web component, handling attribute changes with attributeChangedCallback, and dynamically updating the embedded video based on the provided URL.
Dynamic Rendering
Section Duration: 1 hour, 15 minutes
- Maximiliano discusses creating a router using design patterns to manage client-side URLs effectively, allowing for dynamic content loading without server-side changes. He also demonstrates how to define routes and components within the router.
- Maximiliano walks through how to add a router in JavaScript as a singleton class and discusses the use of the history API to handle navigation and state changes. Maximiliano also touches on event handling, URL manipulation, and the distinction between global variables in the browser context.
- Maximiliano shows how to build a generic router for quickly adding routes to any project. He covers injecting components, handling missing routes, using regex for dynamic paths, and extracting parameters.
- Maximiliano answers questions about passing data into web components and how routing works using URL changes and regex. He also shows how to make the router available globally in the app.
- Maximiliano makes adjustments in the code to ensure proper rendering of pages, including handling 404 errors and dynamic URL routing based on parameters. He demonstrates enhancing link functionality within the router by preventing default actions on link clicks and manually updating URLs without page refreshes.
- Maximiliano discusses the issue of receiving 404 errors when refreshing or bookmarking specific URLs in a web application due to client-side routing not being recognized by the server. He demonstrates how to handle this by creating a catch-all client routes handler in the server-side code to deliver the index HTML for all client-side routes.
- Maximiliano introduces the View Transitions API as a simple way to create smooth transitions between pages without complex CSS animations. By setting specific CSS styles for old and new pages and utilizing the `document.startViewTransition` function, a subtle fade effect can be achieved during page transitions.
- Maximiliano discusses implementing error messages in a web application by creating a dialog element in HTML to display error messages to users. He demonstrates adding functionality in app.js to show error messages and navigate users back to the home page if needed.
Search, Filter, & Sort
Section Duration: 33 minutes
- Maximiliano discusses implementing search functionality in a web application, focusing on constructing query strings for searches and updating URLs accordingly. He also demonstrates parsing URL parameters using URLSearchParams and rendering search results based on query parameters.
- Maximiliano demonstrates debugging a bug related to navigation by identifying the issue in the MovieItem component and addressing it by preventing the default behavior. He also touches on advanced techniques using event listeners and the DOM to enhance user experience and handle event propagation effectively.
- Maximiliano demonstrates how to dynamically load genres from an API and populate a select element in JavaScript. Additionally, he shows how to implement functions for changing search filters and ordering.
Authentication
Section Duration: 1 hour, 44 minutes
- Maximiliano discusses authentication, focusing on user registration, login, and password security. This course will involve creating frontend forms for registration and login, implementing hashing for passwords to enhance security, and discussing the importance of not storing passwords in plain text.
- Maximiliano explains the process of adding a dependency for hashing passwords using bcrypt. He also outlines the steps involved in creating an account management system, including setting up model repositories, handlers for web services like registration and authentication, and corresponding components on the client side.
- Maximiliano discusses the authentication process in a system and the practice of returning generic error messages for unsuccessful login attempts. He also highlights the significance of safeguarding user data and mentions strategies like limiting login attempts to enhance security in large projects.
- Maximiliano explains the importance of handlers, including how they interact with HTTP requests, communicate with repositories, and manage data flow. He also demonstrates the process of creating account handlers and integrating them into the application alongside repositories.
- Maximiliano demonstrates using Postman to send a POST request to an API endpoint, showing how to include data in JSON format and interpret the server response. He also touches on manual method verification in handlers when working with frameworks in Go for different HTTP methods on the same URL.
- Maximiliano explains the process of setting up registration and login functionality on the backend and discusses the need to create corresponding URLs on the client-side for account registration and authentication. He also touches on the significance of associating labels with inputs for accessibility purposes.
- Maximiliano demonstrates creating a web component for a registration page by extending from HTML element and defining the component. He also addresses issues like setting input types explicitly for CSS styling and discusses how browsers handle unclosed tags.
- Maximiliano demonstrates creating a login form and discusses changing attributes like autocomplete to enhance user experience and avoid issues like password manager suggestions on login screens. He also shows how to integrate the login form into a route for seamless navigation between registration and login pages.
- Maximiliano explains the process of creating new API endpoints for registration and login functionalities. He emphasizes the need to send data using a new function called "send" to work with login and registration. Maximiliano also covers client-side validation for user input data before sending it to the server, highlighting the importance of server-side validation as well.
- Maximiliano demonstrates implementing login functionality, with proper validation and error messages. Additionally, he tests registration, confirming the flow is working correctly by creating new user accounts.
- Maximiliano discusses the challenges of user authentication and introduces solutions such as server-side sessions and JSON Web Tokens (JWT) as secure methods to handle authentication without compromising sensitive data.
- Maximiliano explains the process of creating and using JSON Web Tokens (JWT) in Go by utilizing the golang-jwt library. He also demonstrates how to generate a token with user data, encrypt it using a secret key, and validate it.
- Maximiliano explains the importance of storing authentication keys client-side using local storage or IndexedDB for actions requiring authentication. He demonstrates creating a service to store data, like JWT tokens, and using a proxy pattern in JavaScript to manage events like saving token changes to local storage.
Features for Authenticated Users
Section Duration: 59 minutes
- Maximiliano demonstrates how to create an account section for authenticated users in a web application. He also addresses a bug where the account page incorrectly displays a user as logged in even after logging out.
- Maximiliano discusses implementing authentication checks in routes by verifying if a route requires authentication and if the user is logged in. He also explains the process of updating the router to handle authentication requirements.
- Maximiliano demonstrates implementing JWT for user authentication in Go, creating middleware to handle authentication, decrypting JWT, and passing user data through the context to subsequent handlers.
- Maximiliano discusses adding new services to the course app, including getFavorites, getWatchlist, and saveToCollection. He emphasizes the importance of passing authorization tokens manually in API requests and demonstrates how to structure web components using OOP, creating base and extended classes for different sections like favorites and watchlist pages.
- Maximiliano walks through implementing the ability to add movies to favorites and watchlists. He also discusses carefully structuring code, filling API gaps, and ensuring components are correctly imported for a fully functional web application.
Wrapping Up
Section Duration: 5 minutes
- Maximiliano wraps up the course by discussing future feature ideas like account deletion, OTP email confirmation, better password resets, error handling, similar movies, actor pages, and using Go for email.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops