Documentation Index
Fetch the complete documentation index at: https://docs.builderbox.ai/llms.txt
Use this file to discover all available pages before exploring further.
Middleware Setup
1. Configure Protected client routes/pages in apps/web/src/middleware.ts
// apps/web/src/middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getSessionCookie } from "better-auth/cookies";
export const config = {
matcher: [
"/dashboard/:path*",
"/settings/:path*",
"/api/protected/:path*",
],
};
export function middleware(request: NextRequest) {
const sessionCookie = getSessionCookie(request);
const isAuthenticated = sessionCookie !== null;
if (!isAuthenticated) {
return NextResponse.redirect(new URL("/login", request.url));
}
return NextResponse.next();
}
2. Protected API Routes in apps/server/src/routers/index.ts
// apps/server/src/routers/index.ts
import { protectedProcedure, publicProcedure, router } from "../lib/trpc";
export const appRouter = router({
// Public routes
healthCheck: publicProcedure.query(() => {
return { message: "OK" };
}),
// Protected routes
privateData: protectedProcedure.query(({ ctx }) => {
return {
message: "This is private",
user: ctx.session.userId,
};
}),
});
Client-Side Protection
1. Protected Page Component
// apps/web/src/app/dashboard/page.tsx
import { authClient } from "@/lib/auth-client";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const session = await authClient.getSession();
if (!session) {
redirect("/login");
}
return (
<div>
<h1>Dashboard</h1>
<p>Welcome {session.user.name}</p>
</div>
);
}
2. Protected Layout
// apps/web/src/app/(protected)/layout.tsx
import { authClient } from "@/lib/auth-client";
import { redirect } from "next/navigation";
export default async function ProtectedLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await authClient.getSession();
if (!session) {
redirect("/login");
}
return (
<div>
<nav>{/* Navigation */}</nav>
{children}
</div>
);
}
Route Groups
The boilerplate uses Next.js route groups to organize protected and public routes:
app/
├── (auth)/ # Authentication routes
│ ├── login/
│ ├── signup/
│ └── forgot-password/
│ ├── dashboard/ # Protected routes
│
├── about/
└── pricing/
2. Protected Component
// apps/web/src/components/protected-component.tsx
"use client";
import { useAuth } from "@/hooks/use-auth";
import { redirect } from "next/navigation";
export function ProtectedComponent() {
const { user, isLoading, isAuthenticated } = useAuth();
if (isLoading) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
redirect("/login");
}
return (
<div>
<h1>Protected Content</h1>
<p>Welcome {user.name}</p>
</div>
);
}
Security Features
-
Route Protection
- Middleware-based protection
- Server-side session validation
- Client-side session checks
- Automatic redirects
-
Session Management
- Secure session storage
- Session timeout
- Automatic session refresh
- Cross-subdomain support
-
Access Control
- Role-based access
- Permission checks
- Resource ownership
- API route protection
Best Practices
-
Route Organization
- Use route groups
- Separate public/protected routes
- Consistent naming
- Clear structure
-
Error Handling
- Handle loading states
- Show error messages
- Provide fallbacks
- Log errors
-
Security
- Validate sessions
- Check permissions
- Handle edge cases
- Monitor access
Common Issues & Solutions
-
Session Issues
- Check cookie settings
- Verify session storage
- Handle session expiry
- Clear invalid sessions
-
Redirect Loops
- Check middleware matchers
- Verify redirect logic
- Handle edge cases
- Monitor redirects
-
Permission Issues
- Verify role checks
- Check resource access
- Handle missing permissions
- Log access attempts
Next Steps