Routing and Layout
App router page tree, AppLayout shell, admin layout, public vs. authenticated routes, navigation sidebar and bottom-tab-bar.
The frontend uses Next.js App Router with file-system routing. Every page is a page.tsx in a directory matching its URL path. Layouts are either the root layout (app/layout.tsx) or the admin sub-layout (app/admin/layout.tsx); all other pages wrap themselves individually in AppLayout.
Page Tree
/ DiscoverPage - homepage, featured books + categories
├── auth/
│ ├── login LoginPage - email/password form
│ ├── signup SignupPage - registration form
│ ├── forgot-password ForgotPasswordPage - email reset trigger
│ ├── reset-password ResetPasswordPage - new password form
│ └── verify-email VerifyEmailPage - session check after signup
├── book/[id] BookDetailPage - metadata, characters, comments, purchase CTA
├── category CategoryPage - all categories as cards
├── category/[slug] CategoryPage - single category with its books
├── chat ChatPage - recent conversations, library books, live chat UI
├── chat/[id] ChatConversationPage - specific session with SSE streaming
├── checkout/[id] Checkout page - Stripe Elements payment form
├── help HelpPage - static FAQ
├── library LibraryPage - user's owned books, searchable grid
├── notifications NotificationsPage - filterable notification list
├── search SearchPage - results with query params
├── settings SettingsPage - menu hub
├── settings/profile ProfileSettingsPage - avatar, name, bio, email
├── settings/password PasswordSettingsPage - change password form
├── upload-book UploadBookPage - book upload form with file validation
├── wishlist WishlistPage - saved books
└── admin AdminRootLayout + AdminLayout
├── (dashboard) AdminPage - stats cards, activity timeline
├── books BooksPage - search, filter, approve/reject/delete
├── categories CategoriesPage - create, edit, delete with cover upload
├── comments CommentsPage - moderate comments
├── notifications NotificationsPage - system notification CRUD
├── reports ReportsPage - resolve/dismiss user reports
├── settings AdminSettingsPage - platform-wide toggles
└── users UsersPage - search, filter, update roles, block/unblockLayouts
Root Layout (app/layout.tsx)
The single outermost layout that wraps every page. It provides:
- Google Fonts (Geist / Geist Mono)
<AuthProvider>context<Analytics>(Vercel)globals.csswith Tailwind directives
AppLayout (app/app-layout.tsx)
A named-export client component that each page manually imports and wraps its content with. It provides:
- Desktop sidebar - navigation links (Discover, Library, Chat, Settings, Wishlist, etc.), notification bell with unread count, user avatar dropdown, admin panel link for staff users.
- Mobile bottom-tab-bar - same navigation adapted for small screens.
- Admin sidebar - rendered when the
isAdminprop is set.
The AppLayout is not a Next.js layout file - it is a shared component that pages include individually. This was a deliberate choice to keep the auth guard at the page level rather than in a layout that would apply globally.
Admin Layout (app/admin/layout.tsx)
A Next.js layout file that wraps all routes under /admin/. It runs as a server component and:
- Calls
auth()to verify the user is logged in. - Calls
checkIsStaff()to verify the user has admin or moderator role. - Renders an
<AdminSidebar>(server component with user info) and<AdminLayout>(client component for mobile overlay).
Unauthenticated or non-admin users cannot access any /admin/* route.
Navigation
The AppLayout sidebar contains:
- Discover (
/) - browse all books and categories - Library (
/library) - user's purchased/uploaded books - Chat (
/chat) - recent conversations and new chat entry points - Settings (
/settings) - profile, password, appearance, privacy - Wishlist (
/wishlist) - saved books for later purchase - Upload Book (
/upload-book) - book upload form - Notifications - bell icon with unread badge count
- User menu - avatar dropdown with profile link, admin link (if staff), and logout
Public vs. Authenticated Routes
Whether a route requires authentication is determined by two mechanisms:
- Middleware - the server-side edge function checks the URL against a public-route allowlist. Unauthenticated requests to non-public routes are redirected to
/auth/login?error=unauthenticated. - Page-level guards - some pages (library, wishlist, chat, upload-book) additionally call
useAuth()on the client and redirect to login if the user is not authenticated, as a defense-in-depth measure.
Auth pages (/auth/login, /auth/signup, /auth/forgot-password, /auth/reset-password, /auth/verify-email) are standalone - they are not wrapped in AppLayout and use a centered form layout.
Auth Flow
Three-layer auth architecture: edge middleware, server-side helper, client-side context. Supabase Auth with SSR cookies, role-based access, blocked-user enforcement, and debug mode bypass.
API Layer
~40 API routes organized by domain. Auth middleware patterns, admin client usage, backend proxy, stub endpoints, and snake_case conversion at the boundary.