Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Bran258/drtc-fluvial-admin/llms.txt

Use this file to discover all available pages before exploring further.

DRTC Fluvial Admin uses the Next.js App Router, where each directory in app/ corresponds to a URL segment and a page.tsx file opts that segment into rendering. Route groups — directories wrapped in parentheses such as (backoffice) — let you apply a shared layout to a set of pages without those parentheses appearing in the URL. Understanding this structure is the starting point for adding new routes, debugging navigation, and tracing where a given page’s code lives.

Route map

The table below lists every route available in the application, the file that renders it, and the purpose of that page.
URLFilePurpose
/app/page.tsxRedirects immediately to /auth
/authapp/auth/page.tsxStaff login form
/olvide-contrasenaapp/olvide-contrasena/page.tsxPassword recovery
/fluvial/dashboardapp/(backoffice)/fluvial/dashboard/page.tsxMain statistics dashboard
/fluvial/citas/agendaapp/(backoffice)/fluvial/citas/agenda/page.tsxAppointments calendar view
/fluvial/citas/generarapp/(backoffice)/fluvial/citas/generar/page.tsxCreate a new appointment
/fluvial/citas/historialapp/(backoffice)/fluvial/citas/historial/page.tsxAppointment history
/fluvial/tramites/empadronamiento/dashboardapp/(backoffice)/fluvial/tramites/empadronamiento/(dashboard)/dashboard/page.tsxVessel registration overview
/fluvial/tramites/empadronamiento/propietariosapp/(backoffice)/fluvial/tramites/empadronamiento/(dashboard)/propietarios/page.tsxVessel owners list
/fluvial/tramites/empadronamiento/navesapp/(backoffice)/fluvial/tramites/empadronamiento/(dashboard)/naves/page.tsxVessels list
/fluvial/tramites/empadronamiento/opcionesapp/(backoffice)/fluvial/tramites/empadronamiento/opciones/page.tsxRegistration options
/fluvial/tramites/permiso-operacionapp/(backoffice)/fluvial/tramites/permiso-operacion/page.tsxOperation permit management
/fluvial/tramites/renovacionapp/(backoffice)/fluvial/tramites/renovacion/page.tsxPermit renewal
/portal-web/tramitesapp/(backoffice)/portal-web/tramites/page.tsxPublic portal tramites CMS
/portal-web/noticiasapp/(backoffice)/portal-web/noticias/page.tsxPublic portal news CMS

The (backoffice) route group

All authenticated pages live under app/(backoffice)/. The parentheses tell Next.js to treat this as a route group — the segment is invisible in the browser URL bar, but the layout.tsx inside it wraps every child route.
app/(backoffice)/layout.tsx
import Sidebar from "@/shared/components/Sidebar";
import Navbar from "@/shared/components/Navbar";
import Footer from "@/shared/components/Footer";

export default function TransporteFluvialLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="flex h-screen">

      {/* Sidebar */}
      <Sidebar />

      {/* Contenedor principal */}
      <div className="flex flex-col flex-1">

        {/* Navbar */}
        <Navbar />

        {/* Contenido */}
        <main className="flex-1 bg-zinc-100 overflow-y-auto">
          {children}
        </main>

        {/* Footer */}
        <Footer />

      </div>
    </div>
  );
}
Any page you add under app/(backoffice)/ automatically receives the Sidebar, Navbar, and Footer without any additional imports.
The empadronamiento/ directory contains a second nested route group, (dashboard)/, which applies its own sub-layout to the dashboard, propietarios, and naves pages without adding an extra URL segment.

Root redirect

The root page performs a server-side redirect so that visiting / always sends users to the login screen:
app/page.tsx
import { redirect } from "next/navigation";

export default function Home() {
  redirect("/auth");
}

Middleware and route protection

Route protection is implemented in proxy.ts and called from the Next.js middleware. The proxy function reads the accessToken cookie and enforces three rules:
proxy.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function proxy(request: NextRequest) {
  const token = request.cookies.get("accessToken")?.value;
  const pathname = request.nextUrl.pathname;

  const isAuthPage = pathname.startsWith("/auth");

  const isProtectedRoute =
    pathname.startsWith("/fluvial/dashboard") ||
    pathname.startsWith("/fluvial/tramites/permiso-operacion") ||
    pathname.startsWith("/fluvial/tramites/renovacion");

  // Redirect root to /auth
  if (pathname === "/") {
    return NextResponse.redirect(new URL("/auth", request.url));
  }
  // Block protected routes when unauthenticated
  if (!token && isProtectedRoute) {
    return NextResponse.redirect(new URL("/auth", request.url));
  }
  // Redirect authenticated users away from /auth
  if (token && isAuthPage) {
    return NextResponse.redirect(
      new URL("/fluvial/dashboard", request.url)
    );
  }

  return NextResponse.next();
}
The three protection rules are:
ConditionBehavior
pathname === "/"Redirect to /auth
No accessToken cookie on a protected routeRedirect to /auth
Valid accessToken cookie on /authRedirect to /fluvial/dashboard
When you add a new protected route, add its prefix to the isProtectedRoute check in proxy.ts so unauthenticated requests are redirected correctly.

The @/ path alias

tsconfig.json defines a path alias that maps @/ to the repository root:
tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./*"]
    }
  }
}
This means you can write @/lib/axios instead of a relative path like ../../../../lib/axios. Use the @/ alias for all imports that cross directory boundaries.
import axiosInstance from "@/lib/axios";
import { Sidebar } from "@/shared/components/Sidebar";

Build docs developers (and LLMs) love