Superfilter AI
Course Description
Create a full-stack AI-powered Journal app from scratch in Next.js. See how all the pieces of Next.js/React fit together: client components, server components, static and dynamic routing, server actions, middleware, and layouts. Store data in a serverless Prisma DB on PlanetScale and integrate the OpenAI API and Langchain before deploying your app to the world!
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseWhat They're Saying
I took the 'AI-Powered Fullstack Next.js App' course by Scott Moss on Frontend Masters and I have to say it was on point.

Vivek Shukla
whovivekshukla
Learn 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: 8 minutes
- Scott Moss introduces the course and demonstrates the AI-powered application that will be built from scratch with Next.js. The application allows users to log in and manage journal entries with the standard CRUD operations. The entries are analyzed and given an AI-generated sentiment value, summary, and color. The application will be built from scratch, and the final version can be found in the GitHub repo linked below.
App Setup & Authentication
Section Duration: 43 minutes
- Scott uses the `create-next-app` CLI tool to scaffold a new application. Next.js version 13.4.5 is recommended for this course. The default application code is removed, and a Prettier config is added.
- Scott codes the homepage layout. JSX is added and includes a title, description, and a button to take the user to the journal page. Tailwind CSS classes are applied to style the page.
- Scott introduces Clerk, which will handle the application's authentication. Clerk allows multiple auth providers to be configured. The Clerk library is installed, and SignIn and SignUp components are added to their corresponding pages.
- Scott creates a middleware function to ensure all routes except for the home page are protected by the authentication provider. Sign-in and sign-up redirection is configured and the authentication flow is tested.
Connecting to a Database
Section Duration: 47 minutes
- Scott explains why webhooks can help integrate multiple services. When an event in one service is triggered, an API call can push data to another service or server to maintain synchronicity between services. The auth branch can be used as a starting point for this lesson.
- Scott creates a database in PlanetScale, a database environment compatible with serverless applications. The database is provisioned, and the pscale CLI tool is installed, which allows the local application to connect to the database.
- Scott installs and initializes the Prisma ORM. A basic User schema is written and pushed to PlaneScale.
- Scott completes the User and JournalEntry schemas. A relation between the two schemas is established, and Prisma will ensure the names and types between the joined fields match.
- Scott creates the Analysis schema. An analysis contains the mood, summary, color, and a boolean value representing whether the entry is negative.
- Scott creates a database utility method for managing connections. With hot module reloading, multiple database connection objects can be created and cause issues in the application. These utility methods check if the connection has already been established and reuse the existing connection.
Building the Journal Page
Section Duration: 57 minutes
- Scott codes the workflow for creating a new user. When Clerk creates a new user, they are redirected to new-user route where the user data is sent to Prisma. Once Prisma is updated, the user is redirected to the journal page. The db branch can be used as a starting point for this lesson.
- Scott creates the journal page. A layout is created to contain any elements like headers and sidebars that will be reused across the subpages of the journal route.
- Scott demonstrates how to incorporate a user profile widget provided by the Clerk authentication service.
- Scott imports the database helper library to the journal page and creates a getEntries method for retrieving entries from the current user.
- Scott creates EntryCard and NewEntryCard components. These components are responsible for displaying existing entries and creating new entries. They are added to the journal page, and additional Tailwind CSS classes are applied.
Creating & Updating Journal Entries
Section Duration: 1 hour, 7 minutes
- Scott creates the route for the new journal entries. A click handler is used to navigate to the new route by appending the ID of the new entry to the end of the URL. The journal-page branch can be used as a starting point for this lesson.
- Scott adds a few Tailwind CSS classes to the EntryCard component. A Link component is used to navigate to the individual entry page.
- Scott creates the journal entry editor page. This page will display when a user navigates to an individual entry. Issues around the revalidation of data between client and server components are also discussed in this lesson.
- Scott discussed the issues with revalidating data on subsequent routes. Since client and server data are not linked, client-side routes requiring updated data from the server must be revalidated.
- Scott begins adding a text editor to the EntryCard component. A compound constraint must be added to the Prisma schema to select unique entries belonging to the authenticated user. The combination of the user's id and the entry's id creates a virtual key for selecting the entry from the database.
- Scott uses a textarea element as the editor for the journal entry. The client-side state is managed with the useState hook.
- Scott creates a route for updating the entry content. A PATCH method receives the request object and URL parameters. An updateEntry API method is also added to the application.
- Scott implements autosaving with the react-autosave library to save the entry content as the application state is updated. A loading state is added, and debouncing can be controlled with the interval property.
Understanding AI & Prompt Engineering
Section Duration: 45 minutes
- Scott creates the sidebar to display the entry's summary, subject, and mood information. A background color changes based on the overall mood of the entry. The entry-editor branch can be used as a starting point for this lesson.
- Scott introduces Large Language Models (LLMs). One of the most popular LLMs is GPT, created by OpenAI. Prompts and the Langchain framework are also introduced in this lesson.
- Scott walks through how to create an OpenAI API account. First-time users will be given a $5 credit for API usage. A credit card can be added after the credits have expired. An API key is created and added to the applications .env.local file, and the first prompt is sent to the API.
- Scott demonstrates how to provide a prompt that returns consistent results. Giving an example of the data to be returned from the LLM helps create more consistency and reduces the amount of parsing needed back in the application.
- Scott uses the Zod library to supply the LLM with a schema for the results returned from the LMM. Types and descriptions are provided for each data property. Temperature is also explained in this lesson.
Analyzing Entries
Section Duration: 55 minutes
- Scott uses the PromptTemplate object from the Langchain library to create the payload sent to the OpenAI API. The prompt template includes the structured output from the Zod library along with the instructions for the LLM.
- Scott tests the new prompt template and logs the results to the console. The template describes the JSON object needing to be returned and sends general information about JSON so the LLM understands the format.
- Scott updates the journal API so analysis is added to the database when creating a journal entry. The OpenAI API call returns the analysis data, and Prisma writes it to the PlanetScale database.
- Scott uses the include property to pull in the data from the analysis table when selecting a unique journal entry. The analysis data is added to the sidebar UI.
- Scott calls the OpenAI API when entry content is updated. The upsert method is used, so any entries without analysis will have one created. The analyze branch can be used as a starting point for this lesson.
- Scott discusses revalidation and how to update the client UI when a new analysis returns from the API. The sidebar is moved into the Editor component to leverage the client-side state management available to client components.
- Scott adds a couple of navigation links to the left side of the application to navigate to the home page and to the journal page.
Vectors & Similarity Searching
Section Duration: 46 minutes
- Scott creates the UI and writes the client-side code for the search form, allowing users to ask questions to the OpenAI API about the journal entries. The code is wrapped in a client component, so the state and interactivity are available on the client. The analyze-ui branch can be used as a starting point for this lesson.
- Scott introduces vectors and vector databases. Vectors group related data points which simplify the amount of context required for the OpenAI API to respond to a prompt accurately. Each entry will be added to a vector database, and only those closely matching the subject of the prompt will be used in the search analysis.
- Scott codes the helper method to receive a question, creates an in-memory vector database, and performs a similarity search based on the entries. The result is an embedding that can be sent to the OpenAI API for analysis.
- Scott finishes the search feature. The question API endpoint is added to the application. A loading state is added to the Question component, and the results are displayed when a response is received.
Sentiment Analysis
Section Duration: 35 minutes
- Scott adds a sentiment score to each entry to plot the user's mood over time. The score is added to the StructuredOutputParser, and the Prisma schema is updated. The question branch can be used as a starting point for this lesson.
- Scott begins building the history page, which will plot the sentiment scores for the user. The userId is added to the Analysis schema to make it easier to query a user's sentiment scores. This change requires new journal entries to be created.
- Scott imports a charting library and plots the sentiment values on the history page. A custom tooltip component is created, which overrides the default component in the charting library.
Testing & Deployment
Section Duration: 43 minutes
- Scott introduces Vitest and installs the testing dependencies. Configuration files are added to the project, and a setupTests.ts file is created to import the jest-dom testing library.
- Scott creates a test for the home page. To avoid testing the functionality of third-party dependencies like Clerk, mocks are created for the library's methods.
- Scott deploys the app to Vercel. The project is pushed up to a GitHub repo and connected to the Vercel deployment. A production branch of the database is created in PlanetScale, and the schema is migrated.
- Scott answers questions about mocking the OpenAI API and other testing strategies specific to this application.
Wrapping Up
Section Duration: 3 minutes
- Scott generates one last entry from ChatGPT to wrap up the course and encourages engineers to continue building, experimenting, and exploring new technologies.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops