Falsafa
FrontendHigh-Level Design

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/unblock

Layouts

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.css with 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 isAdmin prop 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:

  1. Calls auth() to verify the user is logged in.
  2. Calls checkIsStaff() to verify the user has admin or moderator role.
  3. 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.

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:

  1. 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.
  2. 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.

On this page