diff --git a/frontend/nginx.conf b/frontend/nginx.conf
index 9bc3c7c..bb7577a 100644
--- a/frontend/nginx.conf
+++ b/frontend/nginx.conf
@@ -50,6 +50,11 @@ server {
try_files $uri =404;
}
+ # Raíz sin barra final → login (evita pantalla en blanco por basename)
+ location = /generadorexamenesllm {
+ return 301 /generadorexamenesllm/login;
+ }
+
location / {
try_files $uri $uri/ /index.html;
}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 0b84c72..8bb44fa 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,9 +1,9 @@
import { Navigate, Route, Routes } from "react-router-dom";
import Layout from "./components/layout/Layout";
import ProtectedRoute from "./components/layout/ProtectedRoute";
+import RootRoute from "./components/layout/RootRoute";
import LoginPage from "./pages/LoginPage";
import RegisterPage from "./pages/RegisterPage";
-import DashboardPage from "./pages/DashboardPage";
import CreateTemplatePage from "./pages/CreateTemplatePage";
import TemplateDetailPage from "./pages/TemplateDetailPage";
import NotFoundPage from "./pages/NotFoundPage";
@@ -21,7 +21,7 @@ export default function App() {
}
>
- } />
+ } />
} />
} />
diff --git a/frontend/src/components/layout/RootRoute.jsx b/frontend/src/components/layout/RootRoute.jsx
new file mode 100644
index 0000000..dbbf7a9
--- /dev/null
+++ b/frontend/src/components/layout/RootRoute.jsx
@@ -0,0 +1,17 @@
+import { Navigate } from "react-router-dom";
+import { useAuth } from "../../context/AuthContext";
+import { SpinnerCenter } from "../ui/Spinner";
+import DashboardPage from "../../pages/DashboardPage";
+
+/** Raíz de la app: login si no hay sesión, dashboard si la hay. */
+export default function RootRoute() {
+ const { isAuthenticated, loading } = useAuth();
+
+ if (loading) return ;
+
+ if (!isAuthenticated) {
+ return ;
+ }
+
+ return ;
+}
diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx
index 0ea2e26..69acaf1 100644
--- a/frontend/src/main.jsx
+++ b/frontend/src/main.jsx
@@ -4,8 +4,11 @@ import { BrowserRouter } from "react-router-dom";
import App from "./App";
import { AuthProvider } from "./context/AuthContext";
import { ToastProvider } from "./context/ToastContext";
+import { redirectRootToLoginIfNeeded } from "./utils/redirectRoot";
import "./index.css";
+redirectRootToLoginIfNeeded();
+
ReactDOM.createRoot(document.getElementById("root")).render(
diff --git a/frontend/src/utils/redirectRoot.js b/frontend/src/utils/redirectRoot.js
new file mode 100644
index 0000000..d53abfe
--- /dev/null
+++ b/frontend/src/utils/redirectRoot.js
@@ -0,0 +1,25 @@
+const TOKEN_KEY = "genex_token";
+
+/**
+ * Si el usuario entra en la raíz de la app sin sesión, redirige a /login
+ * antes de montar React (evita pantalla en blanco por basename sin barra final).
+ */
+export function redirectRootToLoginIfNeeded() {
+ const base = import.meta.env.BASE_URL || "/";
+ const baseNoSlash = base.replace(/\/$/, "");
+ const { pathname, search, hash } = window.location;
+ const normalizedPath = pathname.replace(/\/$/, "") || "/";
+
+ const isAppRoot =
+ normalizedPath === baseNoSlash ||
+ normalizedPath === "/" ||
+ pathname === base;
+
+ if (!isAppRoot) return;
+ if (localStorage.getItem(TOKEN_KEY)) return;
+
+ const loginUrl = `${baseNoSlash}/login${search}${hash}`;
+ if (pathname + search + hash !== `${baseNoSlash}/login${search}${hash}`) {
+ window.location.replace(loginUrl);
+ }
+}