Since my experience in front-end development is mostly with React, I recently built a full-stack movie app using the Next.js App Router and PostgreSQL to get more comfortable with these technologies. The app supports searching, adding, editing, and deleting movies, as well as authentication. It’s open source. I’ve also added more comments to the code than I usually do, aiming to make the code easier to follow.
This post is a companion to the source code and gives an overview of the project structure along with explanations of files and directories using a tree UI component. I also share some issues I faced and how I overcame them.
It’s assumed that you have a basic familiarity with the Next.js App Router.
Project Structure
Hydration Mismatch Errors
While building this app, I encountered hydration mismatch errors. I explain the problem and solution in more detail in What Is a Hydration Mismatch Error and How Do You Fix It?.
Redirect From Middleware Not Working Properly With Server Functions
Currently even Nextjs docs mention that you can perform auth checks inside middleware (though they mention this should not be your only line of defense). So you often encounter code like this inside middleware:
if (isProtectedRoute && !session) { return NextResponse.redirect(new URL('/login', req.nextUrl)) }
This works most of the time but there was one situation where it was causing a problem.
Suppose we are on a protected page and the session expires. If then I invoked a server function from that page:
startTransition(async () => { // Call a server function const result = await addMovie(data); // ... });
the addMovie call triggered the middleware. Because we are on a protected page and the session had expired,
the middleware attempted to redirect using NextResponse.redirect (as shown in the previous if check).
However apparently since the middleware was called due to server function, the redirect didn't
happen. The addMovie function itself never ran and simply returned undefined.
It seems others have also encountered this issue, so my solution if from here, to configure the middleware such that it ignores server functions. I do auth checks in server functions though.
Source Code
You can find the source code here.