We use cookies to enhance your experience on the site
CodeWorlds

Route Grouping and Organization

At the heart of the Quantum Metropolis, the urban space management system is based on the concept of thematic districts and functional zones. The city is divided into recognizable areas - a science district, residential zone, entertainment district, and many others. These zones are separated from each other but work together as elements of a single, cohesive urban organism.

Similarly, in Next.js 15, we can organize and group routes in our application to increase code clarity, improve management, and enable more flexible loading strategies and component isolation.

Route Groups

In App Router, we can create route groups that have no impact on the actual URL structure by placing a directory in parentheses, for example:

(groupName)
. This is a powerful feature that allows for logical code organization without changing its behavior or public API.

Route Group Structure and Syntax

Route groups are defined by placing the directory name in parentheses:

1app/
2  β”œβ”€β”€ (marketing)/       # Group for marketing pages
3  β”‚   β”œβ”€β”€ about/
4  β”‚   β”‚   └── page.tsx   # /about
5  β”‚   β”œβ”€β”€ blog/
6  β”‚   β”‚   └── page.tsx   # /blog
7  β”‚   └── layout.tsx     # Shared layout for marketing pages
8  β”‚
9  β”œβ”€β”€ (shop)/            # Group for marketing pages
10  β”‚   β”œβ”€β”€ products/
11  β”‚   β”‚   └── page.tsx   # /products
12  β”‚   β”œβ”€β”€ cart/
13  β”‚   β”‚   └── page.tsx   # /cart
14  β”‚   └── layout.tsx     # Shared layout for shop pages
15  β”‚
16  └── layout.tsx         # Main application layout

In this example, the

/about
and
/blog
routes are part of the
(marketing)
group, while
/products
and
/cart
are part of the
(shop)
group. Note that route groups do not affect the actual URLs - the
(marketing)
directory is not part of the
/about
URL path.

Route Group Applications

1. File and Folder Organization

The simplest use of route groups is logical file organization, especially in larger applications:

1app/
2  β”œβ”€β”€ (main)/               # Main public pages
3  β”‚   β”œβ”€β”€ page.tsx          # Home (/)
4  β”‚   β”œβ”€β”€ about/            # /about
5  β”‚   └── contact/          # /contact
6  β”‚
7  β”œβ”€β”€ (auth)/               # Authentication-related pages
8  β”‚   β”œβ”€β”€ login/            # /login
9  β”‚   β”œβ”€β”€ register/         # /register
10  β”‚   └── forgot-password/  # /forgot-password
11  β”‚
12  β”œβ”€β”€ (dashboard)/          # Dashboard pages (protected)
13  β”‚   β”œβ”€β”€ account/          # /account
14  β”‚   β”œβ”€β”€ settings/         # /settings
15  β”‚   └── billing/          # /billing
16  β”‚
17  └── layout.tsx            # Main layout

2. Sharing Layouts Between Specific Routes

One of the most powerful uses of route groups is the ability to define shared layouts for specific groups of pages without affecting the URL paths:

1// app/(marketing)/layout.tsx - Layout for marketing pages
2export default function MarketingLayout({
3  children,
4}: {
5  children: React.ReactNode;
6}) {
7  return (
8    <div className="marketing-layout">
9      <nav className="marketing-nav">
10        <a href="/about">About Us</a>
11        <a href="/blog">Blog</a>
12        <a href="/careers">Careers</a>
13      </nav>
14      <main>{children}</main>
15      <footer className="marketing-footer">
16        <p>Β© 2150 Quantum Voyages. All rights reserved.</p>
17      </footer>
18    </div>
19  );
20}
1// app/(shop)/layout.tsx - Layout for shop pages
2export default function ShopLayout({
3  children,
4}: {
5  children: React.ReactNode;
6}) {
7  return (
8    <div className="shop-layout">
9      <header className="shop-header">
10        <h1>Quantum Voyages Store</h1>
11        <nav className="shop-nav">
12          <a href="/products">Products</a>
13          <a href="/categories">Categories</a>
14          <a href="/cart">Cart</a>
15        </nav>
16      </header>
17      <main>{children}</main>
18      <aside className="shop-sidebar">
19        <div className="popular-products">
20          <h3>Popular Products</h3>
21          {/* List of popular products */}
22        </div>
23      </aside>
24    </div>
25  );
26}

3. Splitting the Application into Sections

Route groups are particularly useful in multi-section applications, such as an application with a public homepage, admin panel, and user dashboard:

1app/
2  β”œβ”€β”€ (public)/           # Public part of the website
3  β”‚   β”œβ”€β”€ page.tsx        # Home (/)
4  β”‚   β”œβ”€β”€ about/          # /about
5  β”‚   β”œβ”€β”€ blog/           # /blog
6  β”‚   β”‚   └── [slug]/     # /blog/:slug
7  β”‚   └── layout.tsx      # Public layout
8  β”‚
9  β”œβ”€β”€ (admin)/            # Admin panel
10  β”‚   β”œβ”€β”€ admin/          # /admin (uwaga: potrzebny katalog admin/ dla zachowania URL)
11  β”‚   β”‚   β”œβ”€β”€ page.tsx    # /admin
12  β”‚   β”‚   β”œβ”€β”€ users/      # /admin/users
13  β”‚   β”‚   └── settings/   # /admin/settings
14  β”‚   └── layout.tsx      # Admin layout
15  β”‚
16  β”œβ”€β”€ (dashboard)/        # User dashboard
17  β”‚   β”œβ”€β”€ dashboard/      # /dashboard
18  β”‚   β”‚   β”œβ”€β”€ page.tsx    # /dashboard
19  β”‚   β”‚   β”œβ”€β”€ profile/    # /dashboard/profile
20  β”‚   β”‚   └── settings/   # /dashboard/settings
21  β”‚   └── layout.tsx      # Dashboard layout
22  β”‚
23  └── layout.tsx          # Main layout (shared across all sections)

In this example, the application is divided into three main sections, each with its own layout, but all sharing a common main layout.

Quantum Voyages Example

Let's implement a route group system for our space application Quantum Voyages:

1app/
2  β”œβ”€β”€ (marketing)/            # Marketing pages
3  β”‚   β”œβ”€β”€ page.tsx            # Home (/)
4  β”‚   β”œβ”€β”€ about/              # /about
5  β”‚   β”œβ”€β”€ destinations/       # /destinations
6  β”‚   β”‚   └── [id]/           # /destinations/:id
7  β”‚   └── layout.tsx          # Marketing layout
8  β”‚
9  β”œβ”€β”€ (customer)/             # Pages for logged-in customers
10  β”‚   β”œβ”€β”€ dashboard/          # /dashboard
11  β”‚   β”œβ”€β”€ bookings/           # /bookings
12  β”‚   β”‚   └── [id]/           # /bookings/:id
13  β”‚   β”œβ”€β”€ account/            # /account
14  β”‚   └── layout.tsx          # Customer layout
15  β”‚
16  β”œβ”€β”€ (admin)/                # Admin panel
17  β”‚   β”œβ”€β”€ admin/              # /admin
18  β”‚   β”‚   β”œβ”€β”€ voyages/        # /admin/voyages
19  β”‚   β”‚   β”œβ”€β”€ customers/      # /admin/customers
20  β”‚   β”‚   └── analytics/      # /admin/analytics
21  β”‚   └── layout.tsx          # Admin layoutistracyjny
22  β”‚
23  └── layout.tsx              # Main layout

Code for the layouts:

1// app/layout.tsx - Main layout
2import { Inter } from 'next/font/google';
3import './globals.css';
4
5const inter = Inter({ subsets: ['latin'] });
6
7export const metadata = {
8  title: 'Quantum Voyages - Space Travels from the Quantum Metropolis',
9  description: 'Discover space with the Quantum Metropolis guide',
10};
11
12export default function RootLayout({
13  children,
14}: {
15  children: React.ReactNode;
16}) {
17  return (
18    <html lang="pl">
19      <body className={inter.className}>
20        {children}
21      </body>
22    </html>
23  );
24}
1// app/(marketing)/layout.tsx - Marketing layout
2import Header from '@/components/marketing/Header';
3import Footer from '@/components/marketing/Footer';
4
5export default function MarketingLayout({
6  children,
7}: {
8  children: React.ReactNode;
9}) {
10  return (
11    <>
12      <Header />
13      <main className="min-h-screen pt-16 pb-20">
14        {children}
15      </main>
16      <Footer />
17    </>
18  );
19}
1// app/(customer)/layout.tsx - Layout for logged-in customers
2import CustomerHeader from '@/components/customer/Header';
3import CustomerSidebar from '@/components/customer/Sidebar';
4import { checkAuth } from '@/lib/auth';
5import { redirect } from 'next/navigation';
6
7export default async function CustomerLayout({
8  children,
9}: {
10  children: React.ReactNode;
11}) {
12  // Check if the user is logged in
13  const user = await checkAuth();
14  if (!user) {
15    redirect('/login?returnTo=' + encodeURIComponent(window.location.pathname));
16  }
17
18  return (
19    <>
20      <CustomerHeader user={user} />
21      <div className="flex min-h-screen pt-16">
22        <CustomerSidebar />
23        <main className="flex-1 p-6 bg-gray-50">
24          {children}
25        </main>
26      </div>
27    </>
28  );
29}
1// app/(admin)/layout.tsx - Admin layout
2import AdminHeader from '@/components/admin/Header';
3import AdminSidebar from '@/components/admin/Sidebar';
4import { checkAdminAuth } from '@/lib/auth';
5import { redirect } from 'next/navigation';
6
7export default async function AdminLayout({
8  children,
9}: {
10  children: React.ReactNode;
11}) {
12  // Check if the user is an admin
13  const isAdmin = await checkAdminAuth();
14  if (!isAdmin) {
15    redirect('/admin-login');
16  }
17
18  return (
19    <div className="admin-layout">
20      <AdminHeader />
21      <div className="flex min-h-screen pt-16">
22        <AdminSidebar />
23        <main className="flex-1 p-6 bg-gray-100">
24          {children}
25        </main>
26      </div>
27    </div>
28  );
29}

Optional Route Groups

In Next.js 15, we can also create option groups that serve solely for code organization, without any impact on routing or loading logic:

1app/
2  β”œβ”€β”€ (onboarding)/welcome/
3  β”‚                └── page.tsx   # /welcome
4  └── (payments)/cart/
5                  └── page.tsx    # /cart

Separating Layouts and URL Paths

Route groups are particularly useful when we want to share a layout between specific routes that aren't necessarily close to each other in the URL hierarchy:

1app/
2  β”œβ”€β”€ (auth)/
3  β”‚   β”œβ”€β”€ login/         # /login
4  β”‚   β”‚   └── page.tsx
5  β”‚   β”œβ”€β”€ register/      # /register
6  β”‚   β”‚   └── page.tsx
7  β”‚   └── layout.tsx     # Shared layout only for /login and /register
8  β”‚
9  β”œβ”€β”€ account/           # /account (does not use the (auth) layout)
10  β”‚   └── page.tsx
11  β”‚
12  └── layout.tsx         # Main layout dla wszystkich tras

Private Folders (_folderName)

Next.js 15 also introduces the private folders convention, which are marked with an underscore (_) at the beginning of the name. Such folders are not included in URL paths but can contain code shared by multiple routes.

Private Folder Structure and Syntax

1app/
2  β”œβ”€β”€ _components/           # Private folder for shared components
3  β”‚   β”œβ”€β”€ Button.tsx         # Button component
4  β”‚   β”œβ”€β”€ Card.tsx           # Card component
5  β”‚   └── SearchForm.tsx     # Search form component
6  β”‚
7  β”œβ”€β”€ _lib/                  # Private folder for shared functions
8  β”‚   β”œβ”€β”€ api.ts             # API functions
9  β”‚   └── utils.ts           # Utility functions
10  β”‚
11  β”œβ”€β”€ destinations/          # Public route
12  β”‚   └── page.tsx           # /destinations
13  β”‚
14  └── page.tsx               # Home (/)

In this example, the

_components
and
_lib
directories are private and do not generate any URL paths. They are used to store shared components and functions that can be imported by other components.

Difference Between Private Folders and Route Groups

Private folders and route groups look similar but have different use cases:

  • Private folders (
    _folderName
    ) are used to organize code that should not be directly accessible via URL.
  • Route groups (
    (folderName)
    ) are used to group routes without affecting URL paths, but they can influence layout behavior.

Example of Using Private Folders in the Quantum Voyages Application

1app/
2  β”œβ”€β”€ _components/                # Shared UI components
3  β”‚   β”œβ”€β”€ ui/                     # Basic UI components
4  β”‚   β”‚   β”œβ”€β”€ Button.tsx
5  β”‚   β”‚   β”œβ”€β”€ Card.tsx
6  β”‚   β”‚   └── Input.tsx
7  β”‚   β”‚
8  β”‚   β”œβ”€β”€ marketing/              # Components for marketing pages
9  β”‚   β”‚   β”œβ”€β”€ HeroSection.tsx
10  β”‚   β”‚   └── TestimonialCard.tsx
11  β”‚   β”‚
12  β”‚   └── bookings/               # Components for the booking system
13  β”‚       β”œβ”€β”€ BookingForm.tsx
14  β”‚       └── PlanetSelector.tsx
15  β”‚
16  β”œβ”€β”€ _lib/                       # Shared functions and utilities
17  β”‚   β”œβ”€β”€ api/                    # Functions for API communication
18  β”‚   β”‚   β”œβ”€β”€ destinations.ts
19  β”‚   β”‚   └── bookings.ts
20  β”‚   β”‚
21  β”‚   β”œβ”€β”€ hooks/                  # Custom React hooks
22  β”‚   β”‚   β”œβ”€β”€ useBooking.ts
23  β”‚   β”‚   └── useAuth.ts
24  β”‚   β”‚
25  β”‚   └── utils/                  # Helper functions
26  β”‚       β”œβ”€β”€ dates.ts
27  β”‚       └── validation.ts
28  β”‚
29  β”œβ”€β”€ _data/                      # Static data (you can also use /public)
30  β”‚   β”œβ”€β”€ destinations.json
31  β”‚   └── testimonials.json
32  β”‚
33  β”œβ”€β”€ (marketing)/                # Group for marketing pages
34  β”‚   β”œβ”€β”€ page.tsx                # Home (/)
35  β”‚   β”œβ”€β”€ about/                  # /about
36  β”‚   └── destinations/           # /destinations
37  β”‚
38  └── (customer)/                 # Group for customer pages
39      β”œβ”€β”€ dashboard/              # /dashboard
40      └── bookings/               # /bookings

Example code using private folders:

1// app/_components/ui/Button.tsx
2import { cva, type VariantProps } from 'class-variance-authority';
3import { cn } from '@/app/_lib/utils/cn';
4
5const buttonVariants = cva(
6  'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
7  {
8    variants: {
9      variant: {
10        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
11        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
12        outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
13        secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
14        ghost: 'hover:bg-accent hover:text-accent-foreground',
15        link: 'text-primary underline-offset-4 hover:underline',
16      },
17      size: {
18        default: 'h-10 px-4 py-2',
19        sm: 'h-9 rounded-md px-3',
20        lg: 'h-11 rounded-md px-8',
21        icon: 'h-10 w-10',
22      },
23    },
24    defaultVariants: {
25      variant: 'default',
26      size: 'default',
27    },
28  }
29);
30
31export interface ButtonProps
32  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
33    VariantProps<typeof buttonVariants> {
34  asChild?: boolean;
35}
36
37export function Button({
38  className,
39  variant,
40  size,
41  asChild = false,
42  ...props
43}: ButtonProps) {
44  return (
45    <button
46      className={cn(buttonVariants({ variant, size, className }))}
47      {...props}
48    />
49  );
50}
1// app/(marketing)/destinations/page.tsx
2import { getDestinations } from '@/app/_lib/api/destinations';
3import DestinationCard from '@/app/_components/marketing/DestinationCard';
4import { HeroSection } from '@/app/_components/marketing/HeroSection';
5
6export default async function DestinationsPage() {
7  const destinations = await getDestinations();
8
9  return (
10    <div className="container mx-auto px-4 py-12">
11      <HeroSection 
12        title="Discover Space with Quantum Voyages" 
13        subtitle="Browse our space destinations and plan your adventure"
14        image="/images/space-banner.jpg"
15      />
16      
17      <section className="my-12">
18        <h2 className="text-3xl font-bold mb-8">Popular Destinations</h2>
19        
20        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
21          {destinations.map((destination) => (
22            <DestinationCard 
23              key={destination.id}
24              destination={destination}
25            />
26          ))}
27        </div>
28      </section>
29    </div>
30  );
31}

Route Files (route.js)

Next.js 15 enables creating API endpoints using

route.js
(or
route.ts
) files. These files can also benefit from organizational techniques such as route groups and private folders.

API Endpoint Organization

1app/
2  β”œβ”€β”€ api/                      # Main API section
3  β”‚   β”œβ”€β”€ (public)/             # Public endpoints
4  β”‚   β”‚   β”œβ”€β”€ destinations/
5  β”‚   β”‚   β”‚   └── route.ts      # GET /api/destinations
6  β”‚   β”‚   └── newsletter/
7  β”‚   β”‚       └── route.ts      # POST /api/newsletter
8  β”‚   β”‚
9  β”‚   β”œβ”€β”€ (protected)/          # Protected endpoints (require authorization)
10  β”‚   β”‚   β”œβ”€β”€ bookings/
11  β”‚   β”‚   β”‚   β”œβ”€β”€ route.ts      # GET, POST /api/bookings
12  β”‚   β”‚   β”‚   └── [id]/
13  β”‚   β”‚   β”‚       └── route.ts  # GET, PUT, DELETE /api/bookings/:id
14  β”‚   β”‚   └── user/
15  β”‚   β”‚       └── route.ts      # GET /api/user
16  β”‚   β”‚
17  β”‚   └── _middleware/          # Middleware for API (private folder)
18  β”‚       β”œβ”€β”€ auth.ts           # Authentication middleware
19  β”‚       └── rateLimit.ts      # Rate limiting middleware
20  β”‚
21  └── page.tsx                  # Home (/)

Example implementation of a protected API endpoint:

1// app/api/(protected)/bookings/route.ts
2import { NextResponse } from 'next/server';
3import { verifyAuth } from '@/app/api/_middleware/auth';
4import { rateLimit } from '@/app/api/_middleware/rateLimit';
5
6export async function GET(request: Request) {
7  // Verify authentication
8  const authResult = await verifyAuth(request);
9  if (!authResult.isAuthenticated) {
10    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
11  }
12
13  // Rate limiting
14  const rateLimitResult = await rateLimit(request);
15  if (!rateLimitResult.success) {
16    return NextResponse.json({ error: 'Too many requests' }, { status: 429 });
17  }
18
19  // Get bookings for the logged-in user
20  const userId = authResult.user.id;
21  const bookings = await getBookingsForUser(userId);
22
23  return NextResponse.json({ bookings });
24}
25
26export async function POST(request: Request) {
27  // Verify authentication
28  const authResult = await verifyAuth(request);
29  if (!authResult.isAuthenticated) {
30    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
31  }
32
33  // Parse data from the request
34  const data = await request.json();
35
36  // Data validation
37  const validationResult = validateBookingData(data);
38  if (!validationResult.success) {
39    return NextResponse.json({ error: validationResult.errors }, { status: 400 });
40  }
41
42  // Create booking
43  const userId = authResult.user.id;
44  const booking = await createBooking(userId, data);
45
46  return NextResponse.json({ booking }, { status: 201 });
47}

Best Practices for Route Organization in Large Applications

In the Quantum Metropolis, detailed planning is key to the efficient functioning of the city. Similarly, in larger Next.js 15 applications, it's important to follow specific rules and patterns for route organization:

1. Use a Clear and Consistent Structure

Maintain a consistent directory structure and naming throughout the application:

1app/
2  β”œβ”€β”€ (sections)/                 # Groups for main sections
3  β”‚   β”œβ”€β”€ (marketing)/            # Public section
4  β”‚   β”œβ”€β”€ (app)/                  # Main application
5  β”‚   └── (admin)/                # Admin panel
6  β”‚
7  β”œβ”€β”€ _lib/                       # Shared code
8  β”‚   β”œβ”€β”€ components/             # Shared components
9  β”‚   β”œβ”€β”€ hooks/                  # React hooks
10  β”‚   └── utils/                  # Utility functions
11  β”‚
12  β”œβ”€β”€ api/                        # API endpoints
13  β”‚   β”œβ”€β”€ (public)/
14  β”‚   └── (protected)/
15  β”‚
16  └── layout.tsx                  # Main layout

2. Share Components Wisely

Use private folders to store shared components and place them at the appropriate hierarchy level:

  • Components used throughout the application:
    app/_components/
  • Section-specific components:
    app/(section)/_components/

3. Apply Separation of Concerns

  • page.js
    - Page rendering and data fetching
  • layout.js
    - UI layout and navigation logic
  • loading.js
    - Loading states
  • error.js
    - Error handling
  • not-found.js
    - Missing resource handling

4. Use Import Aliases in tsconfig.json/jsconfig.json

Configure import aliases to simplify paths:

1{
2  "compilerOptions": {
3    "baseUrl": ".",
4    "paths": {
5      "@/*": ["./*"],
6      "@components/*": ["./app/_components/*"],
7      "@lib/*": ["./app/_lib/*"],
8      "@hooks/*": ["./app/_lib/hooks/*"],
9      "@utils/*": ["./app/_lib/utils/*"]
10    }
11  }
12}

This allows you to import components in a more readable way:

1// Instead of:
2import Button from '../../../_components/ui/Button';
3
4// You can use:
5import Button from '@components/ui/Button';

5. Implementation for the Quantum Voyages Application

Example of a comprehensive structure for a large Quantum Voyages application:

1app/
2  β”œβ”€β”€ (public)/                    # Public part of the website
3  β”‚   β”œβ”€β”€ _components/             # Components specific to the public section
4  β”‚   β”œβ”€β”€ page.tsx                 # Home (/)
5  β”‚   β”œβ”€β”€ about/                   # /about
6  β”‚   β”œβ”€β”€ destinations/            # /destinations
7  β”‚   β”‚   β”œβ”€β”€ page.tsx             # Destination list
8  β”‚   β”‚   └── [id]/                # /destinations/:id
9  β”‚   β”‚       └── page.tsx         # Destination details
10  β”‚   β”œβ”€β”€ contact/                 # /contact
11  β”‚   └── layout.tsx               # Public layout
12  β”‚
13  β”œβ”€β”€ (auth)/                      # Authentication section
14  β”‚   β”œβ”€β”€ _components/             # Authentication components
15  β”‚   β”œβ”€β”€ _lib/                    # Authentication logic
16  β”‚   β”œβ”€β”€ login/                   # /login
17  β”‚   β”œβ”€β”€ register/                # /register
18  β”‚   β”œβ”€β”€ forgot-password/         # /forgot-password
19  β”‚   └── layout.tsx               # Authentication layout
20  β”‚
21  β”œβ”€β”€ (app)/                       # Main application (dla zalogowanych)
22  β”‚   β”œβ”€β”€ _components/             # Application components
23  β”‚   β”œβ”€β”€ dashboard/               # /dashboard
24  β”‚   β”œβ”€β”€ bookings/                # /bookings
25  β”‚   β”‚   β”œβ”€β”€ page.tsx             # Booking list
26  β”‚   β”‚   β”œβ”€β”€ new/                 # /bookings/new
27  β”‚   β”‚   └── [id]/                # /bookings/:id
28  β”‚   β”‚       β”œβ”€β”€ page.tsx         # Booking details
29  β”‚   β”‚       └── edit/            # /bookings/:id/edit
30  β”‚   β”œβ”€β”€ account/                 # /account
31  β”‚   β”‚   β”œβ”€β”€ page.tsx             # Account overview
32  β”‚   β”‚   β”œβ”€β”€ profile/             # /account/profile
33  β”‚   β”‚   └── preferences/         # /account/preferences
34  β”‚   └── layout.tsx               # Application layout
35  β”‚
36  β”œβ”€β”€ (admin)/                     # Admin panel
37  β”‚   β”œβ”€β”€ _components/             # Admin components
38  β”‚   β”œβ”€β”€ admin/                   # /admin (potrzebny folder dla URL)
39  β”‚   β”‚   β”œβ”€β”€ page.tsx             # Admin dashboard
40  β”‚   β”‚   β”œβ”€β”€ users/               # /admin/users
41  β”‚   β”‚   β”œβ”€β”€ destinations/        # /admin/destinations
42  β”‚   β”‚   └── bookings/            # /admin/bookings
43  β”‚   └── layout.tsx               # Admin layouta
44  β”‚
45  β”œβ”€β”€ _components/                 # Shared components
46  β”‚   β”œβ”€β”€ ui/                      # Basic UI components
47  β”‚   └── forms/                   # Form components
48  β”‚
49  β”œβ”€β”€ _lib/                        # Shared functions
50  β”‚   β”œβ”€β”€ api/                     # API functions
51  β”‚   β”œβ”€β”€ hooks/                   # Custom hooks
52  β”‚   └── utils/                   # Utility functions
53  β”‚
54  β”œβ”€β”€ api/                         # API endpoints
55  β”‚   β”œβ”€β”€ (public)/                # Public API
56  β”‚   └── (protected)/             # Protected API
57  β”‚
58  └── layout.tsx                   # Main layout

Summary

Route grouping and organization in Next.js 15 offers many possibilities for structuring applications in a logical and clear way, similar to how urban zoning in the Quantum Metropolis organizes urban space for maximum efficiency and functionality.

Key concepts:

  1. Route groups (

    (groupName)
    ) - allow logical grouping of routes without affecting URL paths, which is particularly useful for dividing different application sections and implementing specific layouts.

  2. Private folders (

    _folderName
    ) - enable organization of code, shared components, and functions that are not directly accessible via URL.

  3. Hierarchical layouts - the ability to define specific layouts for different route groups, ensuring a consistent user experience within each section.

  4. API organization - applying the same organizational principles to API endpoints.

With these techniques, you can create applications that are:

  • More transparent and easier to maintain
  • Flexible in terms of navigation and user experience
  • Well-organized for development teams
  • Scalable for growing applications

In the next chapter, we'll discover how to handle more complex navigation scenarios, such as nested routes and catch-all parameters, which enable creating advanced and flexible navigation systems in Next.js 15 applications.

Go to CodeWorlds→