
Build a full-stack dating app with Next.js, React, TypeScript, and Tailwind CSS. Implement authentication features, email verification with resend, real-time presence, Cloudinary image uploads, and admin role-based moderation.
Access course assets via the resources button to download the assets zip, and clone or download the GitHub repo to review commits and view code from each section.
Learn practical strategies to troubleshoot Next.js apps: stay calm, solve problems independently, use Google and ai tools, verify versions, restart correctly, and seek detailed help via q&a when needed.
Choose your start point: if you know React and its hooks, proceed to section two on Next.js; otherwise begin with appendix A, introducing React and a simple CRUD app.
Next.js is an opinionated React framework with server-side rendering and file-based routing, using the app folder and page.tsx to enable fast, seo-friendly pages with hydration and dynamic routing.
Explore the inner structure of a Next.js project, including server-side rendering, hot reload, and file-based routing that maps pages, with tailwind and global.css powering styling.
Install and use Hero UI to style a Next.js app, pairing Tailwind CSS with components like animated buttons and react-icons, while configuring providers and imports.
Understand Next.js file and folder based routing, create a members page with page.tsx, navigate with next/link, and apply app layout and nested layouts for consistent routing.
Create a nav bar with a brand, centered content, and Next UI. Style with a gradient background and include links for home, members, lists, messages, and login or register actions.
Create additional routes by adding lists and messages pages, plus login and register paths, adjust Next.js routing with parentheses to ignore folders, and update the navbar for direct links.
Install git and initialize a local repository, then push code to a public GitHub repository by committing changes, configuring a remote origin, and handling authentication with a token.
Explore authentication part one by building login and register forms with react hook form, integrating next door v5, and using prisma orm with middleware to protect routes.
Create a centered login form in a Next.js app using Next UI components (card, input, button) with email and password fields and plan for validation with React Hook Form.
Install and wire up React Hook Form with Zod in a Next.js app, using register and handleSubmit for a TypeScript-first, validated login form with error messages.
Leverage Zod with react-hook-form to validate a login form, defining a login schema with email and a minimum six-character password, using Zod resolver and on touched validation for clear feedback.
Create a register form by copying the login form, add a name field with a three-character minimum using a register schema, and validate with use form and zod.
Explore how NextAuth streamlines authentication in a Next.js app by issuing session cookies, enabling credential and third-party logins, and using JWT for scalable session management.
Explore how Prisma functions as an object relational mapper between code and databases, delivering type-safe queries via a generated Prisma client, migrations, and Prisma Studio with Postgres.
Configure NextAuth and Prisma ORM to enable user login with JWT sessions, using an auth config, Prisma adapter, and API endpoints for sign in and sign out.
Set up a free, serverless Postgres database with Neon Tech and create a project. Copy the connection string and configure Prisma in the env file for Next.js development.
Configure prisma in your app by creating a single shared prisma client, defining user and account models in the schema, pushing to PostgreSQL, and inspecting data with prisma studio.
Register a new user with Next.js 14 server actions, perform client and server validation with Zod, hash passwords with bcrypt, and create a unique user record via Prisma.
Return a discriminated union from server actions with status and data or status and error, and wrap in try-catch to avoid exposing server errors to the client.
Update the register form to display server-side Zod errors using setError and handle server errors like user already exists, with a loading state during submissions.
Configure credential-based sign-in in a Next.js app using a credentials provider, validate login data, and securely compare passwords with bcrypt.
Implement server-side sign-in with next auth in a Next.js app, wiring the login form to server actions, handling credentials errors, and using session cookies to route to the members page.
install react-toastify and add a global toast container to show login error toasts. use toast.error with the error string, position bottom-right, hide progress, and ensure visibility with a high z-index.
Fetch and use the user session data from next-auth on the server side, then pass it to client components and implement sign out via a form.
Leverage next auth callbacks to populate the user id in the session data by using the JWT and session callbacks, inspecting the token subject and returning the updated session.
Add a session-aware dropdown in the navigation bar using Next UI, featuring an avatar trigger and a user actions menu with edit profile via next/link and sign out.
Implement a server action to sign out users, then refresh the page to update the user menu when logging in. Use Next.js middleware to protect routes and restrict unauthenticated access.
Learn to run Postgres locally with Docker, using a Docker Compose file to start a Postgres container and connect your app via a database URL, with Prisma and Prisma Studio.
Configure authentication basics with React forms, validate inputs with Zod, and implement NextAuth with Prisma to enable secure sign-in and registration, while planning for OAuth providers.
Update the Prisma schema to add a one-to-one member model and a one-to-many photo model, with cascading deletes and seed data.
Seed a mock database in a Next.js full-stack app by creating a members data file and seeds script, populating Prisma with test users and images to validate the UI.
Fetches member data from the database via a server action in a Next.js app using Prisma. Filters out the current user with session data and renders a server-side members list.
Create a member card component in a Next.js app, using Next UI Card and a zoomable image, with a responsive grid layout and placeholder handling.
Learn to style responsive member cards in a Next.js app using Tailwind, overlay a dark gradient footer with absolute positioning, turn cards into links, and calculate ages with date-fns.
Implement dynamic routes in Next.js by creating a [userId] page, fetch the member from the database with Prisma, and handle not found via Next.js navigation in a server component.
Builds a left side member sidebar in a Next.js app, with a profile card, navigation links for photos and chat, and a base path using the member id.
Learn to implement a Next.js layout page under a user id route, share a member sidebar with child pages, and fetch member data with deduplicated requests.
Implement Next.js loading indicators by adding a loading dot.tsx that shows a centered spinner during route transitions between photos, chat, and profile pages.
Learn to implement a custom error page in a Next.js app by adding app/error.tsx that gracefully handles server component errors, displays details in a card, and provides a retry option.
Update the prisma schema to model user, photos, and their relationship, seed dummy data, and fetch data in Next.js with server actions and convention-based loading without api endpoints.
Implement a like toggle in a Next.js full-stack app by building server actions with Prisma, handling authorization, and fetching current user like IDs to update the UI.
Build a reusable like button as a client-side React component in a Next.js app, using target id and has liked props to toggle the like and refresh the UI.
Implement list actions in a Next.js full-stack app by fetching liked members, handling source and target likes, and mutual likes with async functions, Prisma queries, and type-based switches.
Create a client component with Next UI tabs to display source, target, and mutual member tabs, passing members and like IDs and updating the URL on tab switch.
Use the useTransition hook in a Next.js app to create a subtle loading state during tab changes driven by query parameters, replacing flicker with a loading component and isPending handling.
Explore many-to-many relationships in Prisma, enabling users to like and be liked, with queries to fetch data and support a favorites feature. Preview upcoming updates to profiles and image uploads.
Explore updating resources by enabling user profile edits and image uploads, using server actions to update and fetch data throughout the full-stack Next.js course.
Build an edit profile form in a Next.js full-stack app by creating an edit form component, a member edit schema with zod, and wiring it with react-hook-form for type-safe editing.
Add the edit member form part 2 with Next UI inputs and on submit to capture data. Preload fields from the member using useEffect and validate errors.
Update member profiles using a server action that validates data with the member edit schema, updates via Prisma, and handles form errors with a reusable handle form server errors utility.
Create a server-side photos page to display a user's images in a grid, fetch the user id and photos, and provide buttons to set a main image or delete it.
Overlay two image actions on a photo—the main-image star and a delete button—using a reusable component with selected and loading states, icons, and a spinner.
Compare image storage options: database, file system, and cloud storage, and adopt Cloudinary for scalable, file-optimized hosting with browser uploads via signed requests, storing image urls and public ids.
Set up secure image uploads with Cloudinary in a Next.js app by creating a free account, obtaining a cloud name, API key, and API secret, and using signed uploads.
Configure Cloudinary and add an image upload button in a Next.js app, wiring a cloud upload button to a sign-image API endpoint to obtain a signed token.
Implement server actions for adding images by updating the Prisma member's photos with the uploaded Cloudinary URL and public ID after a successful upload.
learn to display square profile images by using cloudinary's cloud image component to crop, focus on faces, and handle both cloudinary and local images in a reusable member image component.
Learn to set a main profile image in a Next.js full-stack app by updating user and member images via a server function and refreshing the user interface.
Fix the main image update so the navbar avatar mirrors changes in the sidebar. Ensure profile name edits also refresh in the user menu, all without extra packages.
Present a solution to update the main image, sidebar image, and nav bar image using Prisma database-driven user info instead of cookies, since server-side cookie updates aren't possible.
Section seven introduces a messaging feature with a many-to-many relationship, enabling users to send and receive messages. It sets up the messaging structure for future real-time chat.
Explore setting up Prisma for messages, modeling sender and recipient relations with optional fields and on delete set null, then generate client, push to DB, and create a message form.
Create a chat form in a Next.js app by defining a zod-backed message schema, a reusable card wrapper, and client-side rendering with React Hook Form.
Create a server-side send message action that validates input, saves the message with sender and recipient user IDs via Prisma, and returns form-friendly results while handling errors and updating UI.
Create a server action to fetch a two-way message thread using Prisma, querying messages between the current user and the recipient, ordered oldest to newest, with sender and recipient details.
Flatten and transfer messages efficiently by using a message DTO, mapping Prisma data to a client-friendly structure with sender and recipient details, and formatting dates for UI display.
Display messages in a Next.js chat by rendering a message list and a reusable message box. Use conditional avatars and current user logic to differentiate sent and received messages.
Demonstrates building a chat messages ui in Next.js by composing a render message content component, header with sender and read status, and dynamic speech-bubble styling for current versus other users.
Improve the message box by using useEffect to automatically focus the input on load. Maintain focus after submit and scroll to the bottom on new messages.
Build a messages page sidebar in a Next.js full-stack app, switching between inbox and outbox with a custom tsx navigation, icons, and a query-string based selection.
Implement a fetch messages action in Next.js to retrieve inbox or outbox messages using Prisma, with user ID handling, dynamic sender or recipient queries, and newest-first ordering.
Implement message read functionality in a Next.js full-stack app by marking messages as read with Prisma, updating the database, and bolding unread messages in the chat UI.
Implement a delete message feature in a Next.js full-stack app, manage loading states with use state and use callback, refresh the UI, and truncate long messages in the table.
We wrap up section seven by adding a messaging feature that uses a message join table to support many-to-many relationships, including date sent, read status, and content.
Learn how to implement real-time communications in a Next.js full-stack app with Pusher, adding presence, chat, and notifications via WebSockets, with edge-runtime considerations and options beyond Pusher.
Enable real-time communication with pusher by setting up server and client integrations, using the sandbox for testing, and configuring a reusable pusher instance for live chat in a Next.js app.
learn how to implement live chat in a Next.js app by creating a client side message list component that subscribes to a pusher channel and updates local state.
Understand Next.js caching across router, root, request memoization, and data caches, and how to avoid stale data. Apply force dynamic or revalidate options to control freshness.
Implement read receipts in a next.js app by computing read message IDs, pushing updates with pusher, and updating the other user’s chat ui in real time.
Set up presence with pusher to show who is online by implementing a presence channel, requiring private channel authorization via a dedicated API endpoint at /api/pusher-auth.
Learn how to implement a presence store with zustand to track connected users across a Next.js app, using add, remove, and set methods, and integrate Redux devtools for visibility.
Create a presence channel hook to manage real-time membership with a presence store, subscribing to Pusher, and updating the set, add, and remove methods as users connect or leave.
Subscribe to the presence channel hook at the app level through the providers to track real-time member presence, inspect web sockets, and debug with Redux DevTools.
Update the user interface to display which members are online by building a presence component that reads from a presence store and renders a green online indicator.
Display online presence across avatars, chat, and the sidebar by building a presence avatar component that uses the presence store to show an online indicator for each user.
Set up private channels in pusher to deliver user-specific notifications and inbox updates, with proper authorization. Create a use notification channel that subscribes only for signed-in users.
Implement message notifications in a full-stack next.js app by triggering private channel events with pusher, updating a zustand message store, and refactoring the inbox to global state.
Refactor the message table by moving render logic into a table cell. Move business logic into a use messages hook and ensure props, outbox, deleting, and delete actions in Next.js.
Implement real-time messaging by wiring a message store to initial messages, update the inbox on new messages, and show toasts for off-chat notifications.
Design a custom new message toast inside the use notification channel, supporting a React component and a clickable link to the sender’s chat via Next.js link.
Fetch and display the unread message count in the sidebar and navbar using a get unread message count action, a message store, and Prisma count.
learn to manage unread message counts in a next.js full-stack app by updating on delete, receive, and opening chats, with inbox versus outbox considerations and real-time updates.
Implement a reusable toast notifying users they have been liked (not unliked), including the sender's image and a clickable link to the sender's profile.
Build a general notification toast in a Next.js app by reusing the message toast and passing image, href, title, and subtitle, then trigger like notifications via pusher with user data.
This section enables real-time communication with pusher, including presence, chat, and notifications, and discusses an open-source alternative, then returns to implementing pagination, sorting, and filtering in the user interface.
Discover how to implement sorting, filtering, and pagination with prisma using order by and where queries, and compare offset and cursor pagination for scalable, performant data access.
Learn to implement filtering, sorting, and pagination in a Next.js app, using Next UI components like slider and select for age range and gender filters while optimizing data performance.
Learn how to lay out a non-functional pagination UI using a Next UI component, with hardcoded pages, a page size selector for 3, 6, and 12, styled with Tailwind.
Implement an age slider to filter members on a Next.js server component using query strings and search params, with router.replace for seamless history.
Implement sorting by newest or last active members in a Next.js full-stack app by handling a Next UI selection, updating URL search params, and applying order by with router replacement.
Implement toggleable gender buttons that update the urlsearchparams query string, toggling male and female in a comma-separated list, and use global state management to remember filters across components.
Introduce a Zustand filter store with default age range and gender, expose a setFilters method, integrate devtools, and move logic into a hook to keep filters component focused on UI.
Create a useFilters hook to extract filter logic from the filters component and sync gender, age range, and order by with the URL search params using useEffect and router.replace.
Implement an empty state component that shows a message for no results. Wrap filters in a client side wrapper to render on the members page and prevent query strings.
Learn to implement loading indicators for Next.js filters, including a full-page initial load and a subtle inline spinner during filter transitions using the use transition hook and is pending.
Learn offset pagination, implement a pagination store, and define paging types to track page and size, while syncing the query string to refresh server data.
Connect the pagination store to the pagination component, replacing local state with page number and page size, compute start and end, and update the query string with search params.
Learn to implement pagination in a Next.js app: define a typed query string, use skip and take with Prisma, and reset pages when filters change.
Implement cursor-based pagination in a Next.js app by passing nextCursor to the message table and useMessages hook, with a bottom sticky load more button and a default limit of 10.
Enable a new toggle to filter users by photos, using the Next UI switch and a non-null image condition in Prisma, updating the query string to reflect on/off states.
Learn to activate a with photo filter in a Next.js full-stack app using a switch, update query strings, and return the correct members with or without images.
Explore sorting, filtering, and pagination with prisma queries, and design a ui to support them, compare pagination types, and prepare for upcoming authentication in part two.
Return to authentication in section ten to implement user registration enhancements, email verification, forgot password flows with token-based reset, and social logins via Google and GitHub using resend.
Transform registration into a two-part wizard with React Hook Form's context, secure the presence channel with authentication, and validate age through a Zod profile schema in Next.js using getValues.
Merge the register and profile schemas into a two-step form and switch the validation schema per active step, rendering steps with getStepContent and preserving inputs via form context.
Add an email verification token system in the Prisma schema, create a token table with verification and password reset types, enforce uniqueness, and reset and seed the database.
Implement token generation and retrieval in a Next.js app using Prisma and crypto random bytes to create 24-hour verification tokens, integrate with registration and sign-in flows.
Implement a token-based email verification in a Next.js app by building an auth verify function, a server page, and routes; update email verified property and delete tokens with Prisma.
Implement a forgot password flow in Next.js by generating a reset token, sending a password reset email, and guiding users to a reset password form.
Design and implement a forgot password form as a client component using React Hook Form, with a Next UI email input and a submit button showing a loading state.
Explore how OAuth 2.0 and OpenID Connect enable social logins with Google and GitHub, detailing the authorization flow, tokens, scopes, and the role of the client, resource owner, and servers.
Add social login in the next.js app by introducing google and github buttons, configuring oauth providers and env vars, and updating prisma schema to support sign-in flow and user creation.
Learn how to propagate a profile complete flag through JWT and session in a Next.js app, augment NextAuth types, and gate pusher presence and notifications until users finish their profiles.
Protect social login flows by redirecting users with an incomplete profile to a complete profile page via middleware, using session data to determine status.
Implement a complete profile form for social login using a zod schema, react-hook-form, and a form provider, then update the user profile and re-sign in to issue a new token.
Configure Google as an OAuth provider by creating a Google Developer Console project, obtaining the client ID and client secret, and setting the redirect URL.
Explore secure authentication in a Next.js app, covering user registration, two-step forms, email verification, password resets, social logins with Google and GitHub, and JWT weaknesses.
*** Now updated to use NextJS 15***
Dive into the world of full-stack development with this comprehensive course designed with beginners in mind. This course covers everything from the fundamentals of Next.js to deploying a full-scale application. Whether you are new to programming or looking to expand your existing skills, this course will guide you through every step of building a robust, database driven application.
Here are some of the things that are covered in this course
Creating a Next.js app
Querying a database using Prisma ORM
Securely authenticating users using NextAuth (v5)
Creating a Messaging/Chat feature
Realtime communication using Pusher.
Email verification / Forgot password functionality
Designing the User interface using NextUI
Styling components with TailwindCSS
Utilising server actions to fetch and update the data in Next.js
Image uploading
Publishing the app to the internet with Vercel
Key features of this course
Comprehensive curriculum: 27 hours of high quality video tutorials, challenges and practical content.
Project based learning: Build a major project to showcase your new skills
Pre-Requisites
Basic knowledge of JavaScript, HTML and CSS is recommended.
Tools you need for this course
In this course all the lessons are demonstrated using Visual Studio Code, a free (and fantastic) cross platform code editor. You can of course use any code editor you like and any Operating system you like... as long as it's Windows, Linux or Mac.
Is this course for you?
This course is very practical, about 90%+ of the lessons will involve you coding along with me on this project. If you are the type of person who gets the most out of learning by doing, then this course is definitely for you.
On this course we will build an example Dating Application. All you will need to get started is a computer with your favourite operating system, and a passion for learning how to build a full featured full-stack app based on Next.js.