diff --git a/src/App.jsx b/src/App.jsx
index 8aa384e..b0a8df4 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -50,17 +50,30 @@ const LayoutWrapper = ({ children, currentPageName }) => Layout ?
{children}
: <>{children}>;
-// Routes that render for anyone, signed in or not. LandingPage is pure marketing
-// markup — it reads no entities and never touches useAuth — so the only thing the
-// auth gate ever did for it was bounce visitors to a Google login before they
-// could read what the product is. Its CTAs point at /Dashboard, which is still
-// gated, so signing in stays one click away.
-const PUBLIC_ROUTES = new Set(['/LandingPage']);
+// Paths that render for anyone, signed in or not, skipping the auth gate below.
+//
+// LandingPage is genuinely public: pure marketing markup, no entity reads, so it
+// needs nothing from Base44. Events is not — it lists Event, Staff and VendorRate,
+// all of which stay behind Base44 auth. Opening the route only removes the login
+// redirect; a signed-out visitor gets the page shell with empty lists, because
+// skipping the gate cannot grant data the backend still refuses to serve.
+const PUBLIC_ROUTES = new Map([
+ ['/LandingPage', LandingPage],
+ ['/Events', Pages['Events']],
+]);
-const isPublicRoute = (pathname) => {
- // Tolerate a trailing slash so /LandingPage/ isn't quietly sent to login.
- const normalized = pathname.length > 1 ? pathname.replace(/\/+$/, '') : pathname;
- return PUBLIC_ROUTES.has(normalized);
+const getPublicPage = (pathname) => {
+ // Tolerate a trailing slash, and compare case-insensitively so /events lands on
+ // the same page as /Events — that is how React Router already matches the gated
+ // routes, and a mismatch here would send one casing to login and not the other.
+ const trimmed = pathname.length > 1 ? pathname.replace(/\/+$/, '') : pathname;
+ const normalized = trimmed.toLowerCase();
+ for (const [path, Page] of PUBLIC_ROUTES) {
+ if (path.toLowerCase() === normalized) {
+ return Page;
+ }
+ }
+ return null;
};
// The bare domain is the front door, so it can't be allowed to bounce anonymous
@@ -72,15 +85,13 @@ const AuthenticatedApp = () => {
const { isLoadingAuth, isLoadingPublicSettings, authError, isAuthenticated, navigateToLogin } = useAuth();
const location = useLocation();
- // Ahead of both gates below. The spinner would stall this page on a network
- // round-trip it has no use for, and the auth gate would redirect away from it —
- // either one defeats the point of a public page.
- if (isPublicRoute(location.pathname)) {
- return (
-
- } />
-
- );
+ // Ahead of both gates below. The spinner would stall these pages on a network
+ // round-trip, and the auth gate would redirect away from them — either one
+ // defeats the point of a public route. Rendered bare, without LayoutWrapper,
+ // so the nav chrome doesn't fire its own authenticated queries here.
+ const PublicPage = getPublicPage(location.pathname);
+ if (PublicPage) {
+ return ;
}
// Decided on the token rather than on the resolved auth state, so it settles