App Router Structure
Nexgent uses Next.js 15 with the App Router for server-side rendering, routing, and layouts.
Directory Structure
- layout.tsx
- layout.tsx
- page.tsx
- layout.tsx
- page.tsx
- globals.css
Route Groups
Next.js route groups (folders in parentheses) organize routes without affecting the URL structure.
Auth Routes (auth)
Authentication pages with a minimal layout (no sidebar):
| Route | File | Description |
|---|---|---|
/login | (auth)/login/page.tsx | Login form |
/register | (auth)/register/page.tsx | Registration form |
Dashboard Routes (dashboard)
Protected pages with the full dashboard layout (sidebar, header):
| Route | File | Description |
|---|---|---|
/dashboard | dashboard/page.tsx | Dashboard home (redirects to general) |
/dashboard/general | dashboard/general/page.tsx | Main dashboard with positions |
/dashboard/agent-profile | dashboard/agent-profile/page.tsx | Agent trading configuration |
/dashboard/performance-overview | dashboard/performance-overview/page.tsx | Performance charts and metrics |
/dashboard/trade-signals | dashboard/trade-signals/page.tsx | Signal history |
/dashboard/transactions | dashboard/transactions/page.tsx | Transaction history |
/dashboard/wallet | dashboard/wallet/page.tsx | Wallet management |
/dashboard/integrations | dashboard/integrations/page.tsx | API keys and integrations |
Layouts
Root Layout (app/layout.tsx)
The root layout wraps the entire application with providers:
// app/layout.tsx
import { AppProviders } from '@/shared/providers';
import { Toaster } from '@/shared/components/ui/toaster';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className="dark">
<body className="font-sans">
<AppProviders>{children}</AppProviders>
<Toaster />
</body>
</html>
);
}Dashboard Layout (app/(dashboard)/layout.tsx)
The dashboard layout provides the sidebar and requires authentication:
// app/(dashboard)/layout.tsx
'use client';
import { useSession } from 'next-auth/react';
import { redirect } from 'next/navigation';
import { SidebarProvider, SidebarInset } from '@/shared/components/ui/sidebar';
import { AppSidebar } from '@/shared/components/layout/app-sidebar';
import { Providers } from '@/shared/contexts/providers';
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
const { status } = useSession();
if (status === 'unauthenticated') {
redirect('/login');
}
if (status === 'loading') {
return <LoadingScreen />;
}
return (
<Providers>
<SidebarProvider>
<AppSidebar />
<SidebarInset>
{children}
</SidebarInset>
</SidebarProvider>
</Providers>
);
}The dashboard layout uses Providers from contexts (agent selection, currency, trading mode) which are separate from AppProviders (NextAuth, React Query) at the root.
Page Pattern
Pages are thin wrappers that compose feature components:
// app/(dashboard)/dashboard/general/page.tsx
import { LivePositionsTable } from '@/features/positions';
import { RecentTradesTable } from '@/features/trades';
import { SystemHealthCard } from '@/features/system-health';
export default function GeneralPage() {
return (
<div className="flex flex-col gap-6 p-6">
<h1 className="text-2xl font-bold">Dashboard</h1>
<div className="grid gap-6">
<LivePositionsTable />
<RecentTradesTable />
<SystemHealthCard />
</div>
</div>
);
}API Routes
NextAuth.js uses an API route for authentication callbacks:
// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import { authConfig } from '@/infrastructure/auth/auth-config';
const handler = NextAuth(authConfig);
export { handler as GET, handler as POST };Middleware
Next.js middleware protects routes and handles redirects:
// src/middleware.ts
import { withAuth } from 'next-auth/middleware';
export default withAuth({
pages: {
signIn: '/login',
},
});
export const config = {
matcher: ['/dashboard/:path*'],
};Static vs Dynamic
| Rendering | Usage |
|---|---|
| Static | Landing page, auth pages |
| Dynamic | Dashboard pages (require session) |
Dashboard pages are client components ('use client') because they depend on:
- Session state (authentication)
- WebSocket connections (real-time updates)
- Client-side contexts (agent selection)