Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dev0302/nextjs-project-1/llms.txt

Use this file to discover all available pages before exploring further.

AnonMessage uses a custom Next.js middleware file at src/middleware.ts to enforce authentication rules before any request ever reaches a page or API route. It implements bidirectional redirect logic: unauthenticated users are pushed to sign-in when they try to reach the dashboard, and already-authenticated users are pushed to the dashboard when they try to reach sign-in or sign-up.

Full Middleware Source

import { getToken } from "next-auth/jwt";
import { NextRequest, NextResponse } from "next/server";

export async function middleware(request: NextRequest) {
    const token = await getToken({ req: request });
    const url = request.nextUrl.clone();

    console.log("middleware");

    // If user is logged in and trying to access login/register pages
    if (token && (url.pathname === '/sign-in' || url.pathname === '/sign-up')) {
        return NextResponse.redirect(new URL('/dashboard', request.url));
    }

    // If user is NOT logged in and trying to access protected pages
    if (!token && url.pathname.startsWith('/dashboard')) {
        return NextResponse.redirect(new URL('/sign-in', request.url));
    }

    return NextResponse.next();
}

export const config = {
    matcher: ['/sign-in', '/signup', '/dashboard/:path*']
};

What Middleware Does

Next.js middleware runs on the Edge Runtime before the matched request is forwarded to any server component, client component, or API route handler. It has access to the incoming NextRequest object and can inspect headers, cookies, and the URL, then return a NextResponse that either allows the request through (NextResponse.next()), redirects it, or rewrites it. In AnonMessage, middleware is used for one purpose: reading the NextAuth JWT session cookie and making routing decisions based on whether a valid token exists.

Route Protection Logic

1

Extract the JWT token

const token = await getToken({ req: request });
getToken (from next-auth/jwt) reads the session cookie from the incoming request, decrypts it using NEXTAUTH_SECRET, and returns the decoded JWT payload as a plain object. If no valid session cookie exists — or if it cannot be decrypted — it returns null.
2

Redirect authenticated users away from auth pages

if (token && (url.pathname === '/sign-in' || url.pathname === '/sign-up')) {
    return NextResponse.redirect(new URL('/dashboard', request.url));
}
If a user is already signed in (token is not null) and tries to navigate to /sign-in or /sign-up, they are immediately redirected to /dashboard. This prevents already-logged-in users from seeing the sign-in form.
3

Redirect unauthenticated users away from protected pages

if (!token && url.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/sign-in', request.url));
}
If no valid token exists and the requested path begins with /dashboard, the user is redirected to /sign-in. The startsWith('/dashboard') check covers all nested dashboard routes (e.g., future sub-pages like /dashboard/settings).
4

Allow all other requests through

return NextResponse.next();
Any request that does not match either redirect condition (for example, a user visiting /u/[username] or the landing page) is allowed to continue to its destination unchanged.

The matcher Config

export const config = {
    matcher: ['/sign-in', '/signup', '/dashboard/:path*']
};
The matcher array tells Next.js which URL paths should trigger the middleware function. Requests to paths not listed in matcher bypass middleware entirely — the function is never called for them.
The matcher '/dashboard/:path*' uses Next.js route pattern syntax. The :path* segment matches zero or more path segments, so it covers /dashboard, /dashboard/settings, /dashboard/anything/nested, and so on. The plain string entries /sign-in and /signup match those exact paths only.

Why Only These Routes?

Limiting middleware execution to a small set of paths is a performance best practice. Middleware runs on every matched request, so including paths like /api/* or static assets would add unnecessary latency. By restricting to the three auth-sensitive routes, middleware overhead is essentially invisible.
Note that the matcher includes /signup (no hyphen) but the actual sign-up page lives at /sign-up (with a hyphen). Double-check that matcher entries exactly match your route paths, or unauthenticated users visiting /sign-up will not be caught by the second redirect rule.

Token Extraction and NEXTAUTH_SECRET

getToken({ req: request }) and the NextAuth session system both read the same NEXTAUTH_SECRET environment variable to sign and verify the JWT. This variable must be identical in both places.
// src/app/lib/auth.ts
export const NEXT_AUTH_CONFIG: AuthOptions = {
    // ...
    secret: process.env.NEXTAUTH_SECRET,
    session: {
        strategy: "jwt"
    },
    // ...
}
// src/middleware.ts
const token = await getToken({ req: request });
// getToken reads NEXTAUTH_SECRET from process.env automatically
If NEXTAUTH_SECRET differs between the two contexts (for example, one is set and the other is not), getToken will fail to decrypt the cookie and return null, causing all authenticated users to be treated as guests.
Always define NEXTAUTH_SECRET as a single environment variable and never hardcode it. Use a cryptographically random string of at least 32 characters — you can generate one with openssl rand -base64 32.

Why Not Use NextAuth’s Default Middleware?

NextAuth ships with a ready-to-use middleware export:
// The simple approach — one-directional protection only
export { default } from "next-auth/middleware"

export const config = {
    matcher: ["/dashboard/:path*"]
}
This works for protecting routes, but it only handles one direction: blocking unauthenticated users from protected pages. It does not redirect already-authenticated users away from sign-in or sign-up. AnonMessage’s custom middleware adds the second direction:
ScenarioDefault NextAuth middlewareAnonMessage custom middleware
Guest visits /dashboard✅ Redirects to sign-in✅ Redirects to sign-in
Logged-in user visits /sign-in❌ No redirect — shows sign-in form✅ Redirects to /dashboard
Logged-in user visits /sign-up❌ No redirect — shows sign-up form✅ Redirects to /dashboard

Edge Runtime Constraints

Next.js middleware always runs in the Edge Runtime — a lightweight V8-based environment that does not include the full Node.js standard library. This means middleware must not import Node.js-only modules.
Do not import bcrypt, mongoose, fs, crypto (Node built-in), or any other Node.js-only package inside middleware.ts. These modules are unavailable on the Edge Runtime and will cause a build error or a runtime crash. Database lookups and password hashing belong in API route handlers, not middleware.
getToken from next-auth/jwt is safe to use in middleware because it only performs cryptographic JWT verification using Web Crypto APIs, which are available in the Edge Runtime.

Build docs developers (and LLMs) love