The Heroes App is composed of five page-level components, each mapped to a specific URL route. Three of them (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ludwiigdev/Heroes_App/llms.txt
Use this file to discover all available pages before exploring further.
MarvelPage, DcPage, and SearchPage) are protected routes accessible only after login; HeroPage is likewise protected and handles individual hero details; LoginPage is the only public route. The sections below document each page’s responsibilities, data dependencies, and UI behaviour.
MarvelPage
Route
/marvel — lists all Marvel Comics heroes in a responsive grid.DcPage
Route
/dc — lists all DC Comics heroes in a responsive grid.HeroPage
Route
/hero/:id — detailed view of a single hero with back navigation.SearchPage
Route
/search — live search by hero name driven by the ?q= query parameter.LoginPage
Route
/login — public page with a single button that authenticates the user.MarvelPage
MarvelPage is the default landing page inside the protected area. When a user navigates to /marvel they see a centered heading followed by the complete Marvel Comics hero grid. All data loading and rendering is delegated entirely to HeroList.
Route: /marvel
/ inside HeroesRoutes contains <Navigate to="/marvel" />, so unauthenticated users who successfully log in and have no lastPath stored will also land here first.
DcPage
DcPage mirrors MarvelPage exactly but passes "DC Comics" to HeroList, which filters the hero dataset to DC characters only.
Route: /dc
The heading text in the source reads
"Dc Comics" (lowercase c). This matches the casing in the source file and is intentional.HeroPage
HeroPage renders a full-width detail view for a single hero identified by the :id URL segment. It is navigated to automatically when a user clicks any HeroCard.
Route: /hero/:id
Data flow
Read the route parameter
useParams() extracts the :id segment from the current URL (e.g. "dc-batman" from /hero/dc-batman).Look up the hero
getHeroById(id) searches src/Heroes/data/heroes.js for an entry whose id matches. The call is wrapped in useMemo with [id] as the dependency so it only re-runs when the route parameter changes.Guard against unknown IDs
If
getHeroById returns undefined (the ID does not exist in the dataset), the component immediately renders <Navigate to="/marvel" />, redirecting the user back to the Marvel listing without displaying any broken UI.Layout
Image animation
The hero image receivesanimate__animated animate__fadeInLeft from Animate.css. This slides the image in from the left side on every route visit, providing a polished page-transition feel.
Back navigation
The Regresar button callsnavigate(-1), which moves back one entry in the browser history stack — equivalent to pressing the browser’s Back button. This means the destination is always wherever the user came from (typically the Marvel or DC listing, or the search results page).
SearchPage
SearchPage provides a full-text search experience driven entirely by the URL query string. The search term is stored in ?q=, making searches shareable and bookmarkable.
Route: /search
URL-driven search state
Rather than storing the search term inuseState, SearchPage reads it from the URL:
queryString.parse (from the query-string package) converts location.search (e.g. "?q=flash") into a plain object { q: "flash" }. The default "" ensures q is always a string even when the query parameter is absent.
Search results
superhero field. An empty q always returns an empty array.
UI states
The page has three distinct display states controlled by two boolean flags:| Flag | Condition | UI shown |
|---|---|---|
showSearch | q.length === 0 | Blue info alert: ”🧐 Search a hero to see results!” |
showError | q.length > 0 && heroes.length === 0 | Red error alert: ”❌ No hero found with “ |
| Results grid | heroes.length > 0 | A row-cols-1 row-cols-md-2 grid of HeroCard components |
Form submission
The search form is controlled via the customuseForm hook, initialised with { searchText: q } so the input always reflects the current URL query:
?q= parameter. React Router re-renders the component, queryString.parse reads the new value, and getHeroesByName returns fresh results — all without a page reload.
Navigating to
?q= (with an empty value) or arriving at /search with no query string both result in showSearch = true and an empty results grid, prompting the user to type something.LoginPage
LoginPage is the sole public page in the app. It renders a centred card with a single Login button. There is no username or password field — authentication is simulated for demonstration purposes.
Route: /login
Login flow
User clicks Login
The
onLogin handler fires. It reads lastPath from localStorage — the path the user was trying to reach before being redirected to login (set by PrivateRoute). If no value is stored, it defaults to "/".Authenticate the user
login("Luis Fernandez") is called. Inside AuthProvider, this creates a user object { id: "123", name: "Luis Fernandez" }, persists it to localStorage under the key "user", and dispatches types.login to the reducer, setting logged: true.The
lastPath mechanism works in tandem with PrivateRoute. When an unauthenticated user tries to visit a protected URL, PrivateRoute stores location.pathname in localStorage as "lastPath" before redirecting to /login. After a successful login, LoginPage retrieves that path and redirects there automatically.