
Build a Fullstack Music App with Next.js
A second and third version of this course released using Next 13+, but this course is great if you want to see another example fullstack project. We now recommend you take the Build an AI-Powered Fullstack Next.js App, v3 course.
Table of Contents
Introduction
Code Setup
Setup
Scott briefly walks through the materials utilized in this course, including Node.js, React.js, Postgres, Prisma, Next.js, Vercel, Heroku, and various component libraries. A walkthrough of the finished application is also provided in this segment.Setup Next.js, ESLint, & Typescript
Scott walks through setting up the base for the course project, the code included in a next.js app, and installing the config files and dependencies. Updating file types to TypeScript and a student's question regarding the difference between _app.tsx and index.tsx are also covered in this segment.
App Layout
Course App Overview
Scott discusses an overview of the design layout of the course application and the different components that it is comprised of. Reusable components to look out for when viewing design specifications are also discussed in this segment.Setup Chakra UI
Scott briefly discusses the page rendering options of Next.js and walks through setting up a layout with Chakra UI. Editing the base stylings provided with Chakra UI and extending the theme over the component are also demonstrated in this segment.Creating Player Layout
Scott demonstrates creating the layout for the player component of the course application and briefly discusses Chakra UI's use of box compared to the usual div tag. Wrapping components in the layout avoids the layout being reloaded on page change.Playlist Container Setup
Scott live codes the general layout for the playlist container and sidebar using JavaScript and CSS properties as props with Chakra UI. A student's question regarding how to handle responsive design for the main page if the sidebar is using absolute positioning is also covered in this segment.Creating the Sidebar
Scott walks through implementing the sidebar component, discusses using Chakra's List component to display items, and demonstrates using React Icons to import icon packs as components. Importing all of the Sidebar's needed Chakra and icon components is also shown in this segment.Adding the Logo
Scott demonstrates mocking up the playlist layout to include the playlist container and the provided application logo using NextImage. NextImage is an image component optimized by Next.js and includes image compression. A student's question regarding why height and width for NextImage are set in curly braces and not in quotes is also covered in this segment.
Navigation
Create a List Nav with LinkBox
Scott walks through creating the navigation list in the sidebar using List, ListItem, LinkBox, NextLink, LinkOverlay, and ListIcon. Student questions regarding whether creating objects or code repetition is better for menu items and how NextImage optimizes images are also covered in this segment.Create Playlist Menu
Scott demonstrates creating the music menu, a scrolling playlist menu, and a divider to separate the navigation and music menu from the playlist. The playlist and container must have a height for the application to know where the array is overflowing the container and adequately scroll.
Data Modeling
Setup Prisma & PostgreSQL on Heroku
Scott walks through setting up a PostgreSQL database on Heroku and provides a brief overview of the setup at the end of the segment. Student questions regarding if Prisma works for both SQL and non-SQL databases simultaneously and the need for the shadow database are also covered in this segment.Prisma Schema
Scott demonstrates the syntax of Prisma's schema by setting up a user model with fields, types, and defaults.Data Modeling
Scott demonstrates identifying components and secondary data needed to complete the specified application design. Creating the Song and Artist models are also shown in this segment.Creating Schema & Migrations with Prisma
Scott discusses defining the relations between the previously created models in the Prisma schema. There is a one-to-many relation between User and Playlists due to one user having many playlists. Confirming the changes to the database with an initial migration using Prisma is also covered in this segment.Seeding Data
Scott walks through creating a seed script to populate the database with playlist data and prepare the application for user authentication. Prisma allows the use of nested inserts to avoid multiple database calls. Students' questions regarding the use of Int? for userId and if it is best practice to separate backend code and frontend code are also covered in this segment.Running the Seed Script
Scott walks through how to run the seed script to populate the application's database. A demonstration of using Prisma studio to view the database in a browser application is also provided in this segment.Seeding User Data
Scott demonstrates how to salt and hash users' passwords using bcrypt for encryption. A student's question regarding if the Prisma code gets shipped to the client is also covered in this segment.Seeding Playlist Data
Scott live codes the seed script for new playlist arrays to populate the playlist data in the database. This seed script will also connect the playlists to a user.Seeding Playlist Data Q&A
Scott answers student questions regarding when the run function gets executed and if running the seed script clears the previous data in the database.
Authentication
Serverless API Overview
Scott discusses the benefits and drawbacks of building out database routes frontend first, backend first, and by feature. A demonstration of API routes corresponding to files in the pages/api folder and discussion of serverless functions being functions that are executed based on an event are also covered in this segment.Signup API Route
Scott walks through creating a serverless signup function for user account creation and authentication. Student questions regarding if Prisma can generate and validate CSRF tokens and how serverless functions execute in production are also covered in this segment.Signup API Route Recap & Test
Scott walks through the previously completed signup API route and tests to verify that the route creates a user and erroring when creating an already existing user.Signin API Route
Scott live codes and tests the serverless signin function, allowing users to sign in to their account by comparing the user email and password to the data stored in the database. This function will also respond to an incorrect username or password input with an error.Fetcher & Auth Mutation
Scott creates a fetcher function to abstract the HTTP fetching mechanism and an auth mutation function to make an API call to sign in or sign up using the fetcher function. Scott also creates a mutations file to hold the various functions mutating the application's state.Auth Pages
Scott walks through building an authForm component to toggle between modes based on the user login status and demonstrates opting out of the global player layout for just the login page. This form is created using useRouter to access the Next.js router and userSWRConfig, which can handle data fetching, caching, optimistic updates, re-fetching, and re-caching.Sign In & Sign Up
Scott live codes the authForm inputs, submission button, form styling, and logo for signin and signup. Implementing the forms to allow users to sign in and signup is also covered in this segment.Protected Route Handler
Scott demonstrates only allowing authorized users, protecting API routes using middleware, and discussing protecting pages utilizing edge functions. Student questions regarding why the user is added for the handler argument and a reason for not using NextAuth for authentication are also covered in this segment.
Middleware
Middleware Edge Functions
Scott walks through creating an edge function that checks the cookie to see if the user has a valid access token and redirects to the sign in page if no token is found. Student questions regarding ending test edge functions on localhost, if _app.tsx runs before _middleware.tsx, and if NextResponse is replacing res.Middleware Q&A
Scott answers student questions regarding limited options for deploying a Next.js application and ways to redirect 404 pages. A student's question regarding if there is any relation between middleware functions and Angular interceptors is also covered in this segment.
Fetching Data
Custom Hooks for Fetching Data
Scott demonstrates creating custom hooks with SWR to handle fetching the user and playlists data from the server and setting the correct loading state. A student's question regarding if the word "use" has to be in the function name is also covered in this segment.Fetch & Render Data into Components
Scott walks through using the custom usePlaylist hook to fetch the playlist data, allowing a user's playlists to be rendered in the sidebar component. The usePlaylist hook can be used to avoid making multiple calls for every page that includes playlists.
UI Layout
Gradient Background & Image Box
Scott live codes a gradient page component for the homepage and playlist gradient background using Chakra UI's Box and Flex components. Creating a flexible image box for the user profile picture and playlist image is also covered in the segment.Title & Subtitle UI Layout
Scott demonstrates using Chakra UI's Text component to abstract away from heading, paragraph, or span tags being used for text. The Text component will default to a paragraph tag but can be changed to an alternate tag by setting the "as" property value.Load Artists Data
Scott demonstrates retrieving data from the server by exporting the getServerSideProps function from Next.js. Despite being located in a page component, the getServerSideProps function only runs server-side and never runs on the browser. A student's question regarding the difference between getStaticProps and getServerSideProps is also covered in this segment.Artists List UI Layout
Scott walks through implementing the layout and styling for the artists list, including rendering the artists data previously retrieved from the server. Each artist card will include a placeholder image, artist name, and " Artist " label.
Dynamic UI
Seed User Data
Scott walks through resetting the database to include new user data and pulling in the user data to replace the application's hard-coded data. Populating the user playlist count is also covered in this segment.Build Dynamic Playlist Pages
Scott live codes a dynamic route for playlist pages that will render and authenticate a page for each user's playlists. The server request will also get the songs and artists in each playlist. Student questions regarding if the include keyword is similar to a join and if the playlist request returns everything about songs unless specified are also covered in this segment.Playlist Page UI
Scott continues to work on the playlist page by implementing the previously created gradient layout, a random background color generator, and a random playlist image.Songs Table UI
Scott walks through starting to build out the songs table to hold the songs in the user's playlists, including the layout of the play button and completion of the table header. The Chakra UI Table component is imported and used to build the songs table.Song UI & Time format
Scott demonstrates inserting song data into the songs table, including song number, title, date added, and song duration. The formatting functions used to format date added and song duration into appropriate time formats are built using the Format Duration library. Student questions regarding if getServerSideProps has to be named exactly that and if edge functions compared to lambda functions are expensive to hold on a live CDN
State Management
Auth Error Handling
Scott discusses the scope of what will be covered regarding the player component and how to handle auth errors with an expired jwt by redirecting a user to the login page.Player UI Container
Scott walks through creating the container layout for the application's player bar component using Chakra UI's Box, Flex, and Text components.Player State with Easy Peasy
Scott demonstrates creating a store and player state using the Easy Peasy library to handle the active playlist and song state.Player Controls UI
Scott live codes importing components for the seek bar and the controls for the player bar using Chakra UI, React, React Howler, React Material Design Icons, and Easy Peasy to access the application's store. The shuffle, previous, play, pause, and next buttons are laid out in this segment.Seek Bar UI
Scott walks through implementing the sidebar component, discusses using Chakra's List component to display items, and demonstrates using React Icons to import icon packs as components. Importing all of the sidebar's needed Chakra and icon components is also demonstrated in this segment.Player Controls State
Scott walks through setting up state for the player using Easy Peasy, including shuffle, repeat, play, current duration, seek bar value, seeking, and currently playing song. Student questions regarding if useReducer is used to eliminate the state, if the playState wrapper is redundant, and why setPlayState does not follow the onShuffle/onRepeat naming convention are also covered in this segment.Playing Songs State
Scott demonstrates how to import and set the player's active song, conditionally render the artist box and player component, and render the current song and artist names.
Callbacks
Shuffle and Next Song Controls
Scott walks through syncing the player UI with the music with reference to the native JavaScript Howler instance by attaching a reference to the React Howler component. The controls covered in this segment are next and previous, including when shuffle is active and hitting the last song of the playlist.Seek Bar Controls
Scott implements seek bar controls, including the onEnd, onLoad, and the range slider functions to handle the seek bar functions. Student questions regarding if the seek bar controls could be used for the volume slider and if the player would be a good candidate for Xstate are also covered in this segment.requestAnimationFrame & Synching UI
Scott demonstrates updating the UI to be responsive to changes using the requestAnimationFrame method, which tells the browser that an animation wishes to be performed and requests that the browser calls a specified function to update an animation before the next repaint. Updating the range slider and the current song duration are covered in this segment.End Song & Repeat Handlers
Scott walks through implementing and debugging the player's next, previous, repeat, and shuffle functions. Using a reference instead of hooks with callbacks can help avoid getting caught in closures.
Deployment & Testing
Deploying with Vercel
Scott discusses a brief overview of the completed application and walks through the deployment process with Vercel. If Vercel is connected to a GitHub repository, it will automatically redeploy on a new push to that repository.Testing & CI
Scott discusses different options for adding testing and CI to the application, including Jest, Cypress, and GitHub Actions. Student questions regarding if Next.js has a configuration to do a static build for all pages, opinions on React testing library, and if user details can be server-side rendered with SWR are also covered in this segment.