Skip to content

bug: improve 404 page with search, back navigation and bug report#4376

Open
Ranjan-githu wants to merge 4 commits into
anurag3407:mainfrom
Ranjan-githu:feature/improve-404-page
Open

bug: improve 404 page with search, back navigation and bug report#4376
Ranjan-githu wants to merge 4 commits into
anurag3407:mainfrom
Ranjan-githu:feature/improve-404-page

Conversation

@Ranjan-githu

@Ranjan-githu Ranjan-githu commented Jul 2, 2026

Copy link
Copy Markdown

User description

Description

Summary

This PR improves the 404 (Not Found) page by adding helpful navigation and recovery options for users.

Changes Made

  • Added a search section using the existing SearchInput component.
  • Added a Go Back button using navigate(-1).
  • Added a Report Broken Link button using the existing ReportBugModal.
  • Displayed the invalid URL that the user attempted to access.
  • Preserved the existing terminal animation and overall design.

Why

The previous 404 page only provided a single action (git checkout dashboard), making it difficult for users to recover from navigation errors. These additions improve the user experience by providing multiple recovery options while maintaining the existing look and feel.

Acceptance Criteria

  • ✅ Search input added with useSearchParams
  • ✅ Go Back button added
  • ✅ Report Broken Link button added
  • ✅ Invalid URL displayed
  • ✅ Existing animation preserved

Type of Change

Bug fix

Related Issue

Fixes #4259

Testing

Unit tests pass
Tested Locally

Screenshots (MANDATORY for UI/UX changes)

before
image
After
image

Checklist

Code follows project style guidelines
Self-reviewed my code
Added comments where necessary
No new warnings generated

Summary by CodeRabbit

  • New Features
    • Enhanced the 404 page with a built-in search field and quick actions: go back, return to the dashboard, and report a broken link.
    • Added a “Report this broken link” modal with a prefilled message and one-click copy-to-clipboard with success/error feedback.
  • Bug Fixes
    • Display the invalid URL directly on the 404 page.
    • Kept the search query synchronized with the page URL consistently (without adding a new history entry).
  • Tests
    • Added a unit test covering the 404 page’s search-query synchronization behavior.

CodeAnt-AI Description

Make the 404 page help users search, go back, or report a broken link

What Changed

  • The 404 page now shows the URL that could not be found
  • Users can search directly from the 404 page, with the search query kept in the page URL
  • Added a Go Back action, a return-to-dashboard action, and a broken-link report button
  • Reporting a broken link opens a prefilled copy-to-clipboard message so users can share the issue quickly
  • Added coverage for keeping the search query in sync without adding a new history entry

Impact

✅ Easier recovery from broken links
✅ Faster navigation back to a working page
✅ Clearer broken-link reports

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

@Ranjan-githu is attempting to deploy a commit to the Anurag Mishra's projects Team on Vercel.

A member of the Team first needs to authorize it.

@codeant-ai

codeant-ai Bot commented Jul 2, 2026

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.

@codeant-ai

codeant-ai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a ReportBugModal for broken-link reporting and updates NotFound.jsx to add search, back navigation, URL query syncing, and a report action. It also adds a NotFound test and stores the Vitest run result.

Changes

404 Page Enhancements

Layer / File(s) Summary
ReportBugModal component
frontend/src/components/ReportBugModal.jsx
New modal component with framer-motion transitions, a textarea prefilled from invalidPath, and a submit handler that copies the report to the clipboard with toast success/error feedback.
NotFound page search, navigation, and report integration
frontend/src/pages/NotFound.jsx
Adds useSearchParams-based searchQuery state synced to the URL, derives invalidPath, and replaces the actions UI with a SearchInput, "Go Back" button, dashboard link, invalid URL display, and a "Report this broken link" button wired to ReportBugModal.
NotFound test and Vitest result
frontend/src/__tests__/NotFound.test.jsx, frontend/vitest-notfound.json
Mocks router hooks and child components, verifies setSearchParams is called with replace: true, and includes the saved Vitest execution result for that test run.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant NotFound
  participant SearchInput
  participant ReportBugModal

  User->>NotFound: Visits invalid URL
  NotFound->>NotFound: Derive invalidPath, searchQuery
  NotFound->>SearchInput: Bind searchQuery
  User->>SearchInput: Types query
  SearchInput->>NotFound: Update searchQuery
  NotFound->>NotFound: Sync searchQuery to URL params
  User->>NotFound: Clicks "Report this broken link"
  NotFound->>ReportBugModal: Open with invalidPath
  User->>ReportBugModal: Submit report
  ReportBugModal->>ReportBugModal: Copy report to clipboard
  ReportBugModal->>NotFound: Close modal
Loading

Possibly related PRs

  • anurag3407/career-pilot#39: Both PRs modify frontend/src/pages/NotFound.jsx; PR #39 created the original terminal-style 404 page that this PR extends with search/CTA and bug report behavior.

Suggested labels: type:design, level:intermediate

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR adds the three requested CTAs, uses search params, and pre-fills the report modal with the attempted URL.
Out of Scope Changes check ✅ Passed The changes stay focused on the 404 recovery flow and its supporting test artifacts, with no clear unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main 404-page improvements: search, back navigation, and bug reporting.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Jul 2, 2026
Comment on lines 44 to +104
@@ -73,16 +85,53 @@ const NotFound = () => {
</div>
</div>

{/* Action Button */}
<Link
to="/dashboard"
className="px-8 py-4 bg-[#00ffaa] text-[#0a0a0a] font-bold rounded-xl transition-all duration-300 transform hover:scale-105 hover:bg-[#00e699] active:scale-95 focus:outline-none focus:ring-2 focus:ring-[#00ffaa] focus:border-transparent flex items-center gap-2 shadow-[0_0_30px_rgba(0,255,170,0.2)]"
>
<span>git checkout dashboard</span>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clipRule="evenodd" />
</svg>
</Link>
{/* Search + CTA Section */}
<div className="w-full max-w-xl space-y-6 mb-10">
<div className="rounded-3xl border border-white/10 bg-[#111111]/80 p-6 shadow-2xl">
<div className="mb-4 text-sm text-neutral-400">Search this path or refine your query</div>
<SearchInput
name="notfound-search"
value={searchQuery}
placeholder="Search for a page, feature, or help topic"
onChange={setSearchQuery}
wrapperClassName="w-full"
/>
</div>

<div className="grid gap-3 sm:grid-cols-3">
<button
type="button"
onClick={() => navigate(-1)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Updating search params on each query change pushes new history entries by default, so the “Go Back” action can step through many local query updates instead of returning to the previous page. Use replace-mode updates for these in-page query sync writes to avoid polluting navigation history. [logic error]

Severity Level: Major ⚠️
- ❌ Go Back button often fails to leave 404 page.
- ⚠️ Browser back stack polluted by search param entries.
- ⚠️ Users must click back many times to exit 404.
- ⚠️ Navigation UX degraded specifically on NotFound route.
Steps of Reproduction ✅
1. Navigate to any existing page in the app, then follow a link or manually enter a URL
that does not match any defined route (e.g. `/nonexistent-feature`); the catch-all route
`<Route path="*" element=<NotFound /> />` in `frontend/src/App.jsx:64-65` renders
`frontend/src/pages/NotFound.jsx`.

2. In `NotFound.jsx`, the search state and URL syncing are set up at lines 9-11 and 44-46:
`useSearchParams()` provides `[searchParams, setSearchParams]` (line 9), `searchQuery`
state is initialised from `searchParams.get('q') || invalidPath` (line 11), and the effect
at lines 44-46 calls `setSearchParams({ q: searchQuery });` on every `searchQuery` change.

3. Type a multi-character term into the `SearchInput` rendered at lines 88-99.
`SearchInput` internally debounces and calls the parent `onChange={setSearchQuery}`
(`frontend/src/components/SearchInput.jsx:62-67` and `NotFound.jsx:96`), causing
`searchQuery` in `NotFound` to change several times as the user types (e.g. "r", "re",
"res", "resume").

4. Each `searchQuery` update triggers the effect at `NotFound.jsx:44-46`, which calls
`setSearchParams({ q: searchQuery })` with default push behavior, creating a new browser
history entry for each intermediate query value on the same NotFound route. When the user
clicks the "Go Back" button at lines 102-107 (`onClick={() => navigate(-1)}`), navigation
steps back through these local query-only history entries instead of returning to the
previous page, so back navigation appears to "do nothing" or only change the URL’s `q`
parameter while keeping the user stuck on the 404 screen.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/pages/NotFound.jsx
**Line:** 44:104
**Comment:**
	*Logic Error: Updating search params on each query change pushes new history entries by default, so the “Go Back” action can step through many local query updates instead of returning to the previous page. Use replace-mode updates for these in-page query sync writes to avoid polluting navigation history.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done please review my changes

@codeant-ai

codeant-ai Bot commented Jul 2, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

@Ranjan-githu

Copy link
Copy Markdown
Author

Hi @maintainers,

I've submitted a PR for this issue: #4259

The PR includes:

  • Search functionality using the existing SearchInput
  • Go Back navigation
  • Report Broken Link integration
  • Invalid URL display
  • Preservation of the existing terminal animation and design

I'd appreciate your feedback. Thank you!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
frontend/src/components/ReportBugModal.jsx (1)

35-48: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Exit animations never run — no AnimatePresence in the tree.

exit props on both motion.divs (lines 38, 46) are inert here since the component returns null directly (line 29-31) instead of being conditionally rendered inside <AnimatePresence>. Without it, the exit prop does absolutely nothing and the modal will disappear instantly rather than animating out.

Fixing this requires the parent (NotFound.jsx) to wrap the <ReportBugModal> render with <AnimatePresence> and gate rendering by isOpen there, rather than short-circuiting inside this component.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/ReportBugModal.jsx` around lines 35 - 48, The modal’s
`exit` animations in `ReportBugModal` are currently inert because the component
short-circuits to `null` before Framer Motion can animate unmounting. Move the
conditional rendering to the parent `NotFound` component so `<ReportBugModal>`
is mounted/unmounted inside `<AnimatePresence>`, and gate it with `isOpen`
there. Keep the `motion.div` `exit` props in `ReportBugModal`, but ensure the
parent controls visibility rather than returning `null` inside the modal itself.
frontend/src/pages/NotFound.jsx (1)

101-121: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

LGTM on the CTA wiring for Go Back / dashboard link / report trigger — the duplicated Tailwind class strings between the two secondary buttons (Lines 102-108, 115-121) could be extracted into a shared class constant, but this is purely cosmetic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/NotFound.jsx` around lines 101 - 121, The two secondary
buttons in NotFound share the same Tailwind class string, so extract that
repeated styling into a shared constant within NotFound.jsx and reuse it for
both the Go Back and Report this broken link buttons. Keep the existing button
behavior and text unchanged, and use the shared class name near the button JSX
to make the duplication easy to spot.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/ReportBugModal.jsx`:
- Around line 33-48: The ReportBugModal overlay currently lacks accessible modal
behavior, so update the modal container in ReportBugModal to expose proper
dialog semantics and keyboard support. Add dialog attributes and a
label/description hookup on the main motion.div, wire Escape key handling to
call onClose, and ensure the modal grabs initial focus when opened and keeps
focus trapped within it until dismissed. Use the existing onClose prop and the
modal wrapper elements in ReportBugModal to implement this cleanly.

In `@frontend/src/pages/NotFound.jsx`:
- Around line 2-12: Freeze the originally requested URL in NotFound and stop
deriving it from the live location/search state after mount. Use a stable ref or
memo in NotFound (around useLocation, useSearchParams, and invalidPath) to
preserve the initial path/query for the report modal, and change the
search-param sync so setSearchParams for q uses replace: true instead of pushing
a new history entry. Keep searchQuery initialization and modal prefill tied to
the frozen initial value so edits are not wiped when location.search changes.

---

Nitpick comments:
In `@frontend/src/components/ReportBugModal.jsx`:
- Around line 35-48: The modal’s `exit` animations in `ReportBugModal` are
currently inert because the component short-circuits to `null` before Framer
Motion can animate unmounting. Move the conditional rendering to the parent
`NotFound` component so `<ReportBugModal>` is mounted/unmounted inside
`<AnimatePresence>`, and gate it with `isOpen` there. Keep the `motion.div`
`exit` props in `ReportBugModal`, but ensure the parent controls visibility
rather than returning `null` inside the modal itself.

In `@frontend/src/pages/NotFound.jsx`:
- Around line 101-121: The two secondary buttons in NotFound share the same
Tailwind class string, so extract that repeated styling into a shared constant
within NotFound.jsx and reuse it for both the Go Back and Report this broken
link buttons. Keep the existing button behavior and text unchanged, and use the
shared class name near the button JSX to make the duplication easy to spot.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 84832d5e-3232-4c1d-b7b9-ff931b1806e3

📥 Commits

Reviewing files that changed from the base of the PR and between 0b4f739 and 59fc54f.

📒 Files selected for processing (2)
  • frontend/src/components/ReportBugModal.jsx
  • frontend/src/pages/NotFound.jsx

Comment thread frontend/src/components/ReportBugModal.jsx
Comment thread frontend/src/pages/NotFound.jsx
@codeant-ai

codeant-ai Bot commented Jul 3, 2026

Copy link
Copy Markdown

CodeAnt AI is running Incremental review

@codeant-ai

codeant-ai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Jul 3, 2026
@codeant-ai

codeant-ai Bot commented Jul 3, 2026

Copy link
Copy Markdown

CodeAnt AI Incremental review completed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
frontend/src/__tests__/NotFound.test.jsx (2)

11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Confusing/unrealistic mock: location.search embeds q=abc while useSearchParams() is mocked empty.

In real react-router, useLocation().search and useSearchParams() are derived from the same URL and would be consistent. Here location.search is '?q=abc' (looking like an existing query param) while useSearchParams() returns an empty URLSearchParams, so the assertion only passes because searchParams.get('q') falls through to invalidPath. Consider using a search string without a q= substring (e.g., ?foo=bar) to avoid the coincidental overlap and make the test's intent clearer.

Proposed clarification
-    useLocation: () => ({ pathname: '/missing', search: '?q=abc' }),
+    useLocation: () => ({ pathname: '/missing', search: '?foo=bar' }),

and update the assertion to '/missing?foo=bar' accordingly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/__tests__/NotFound.test.jsx` around lines 11 - 13, The NotFound
test mock is inconsistent because NotFound’s location search and useSearchParams
values should reflect the same URL, but the current pathname/search combination
creates a misleading q=abc overlap. Update the mocked useLocation() search in
NotFound.test.jsx to a query string without q=... (for example, a different
param), and adjust the expectation in the NotFound assertion so it matches the
new URL shape used by the component.

30-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test only covers query-sync effect; missing coverage for Go Back and Report Broken Link CTAs.

Per the linked issue's acceptance criteria, the 404 page must provide three CTAs: search, go back, and report (with the attempted URL pre-filled). This suite verifies only the setSearchParams sync behavior — there's no assertion that clicking "Go Back" calls navigate(-1), or that opening the report modal passes the invalid URL through. Consider adding tests for these paths given they're the PR's core acceptance criteria.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/__tests__/NotFound.test.jsx` around lines 30 - 38, The NotFound
test suite only covers the query sync behavior, but it still needs coverage for
the other acceptance-criteria CTAs. Add tests around the NotFound component that
verify clicking the Go Back CTA triggers navigate(-1), and that the Report
Broken Link CTA opens the report flow with the attempted URL passed through as
the prefilled value. Use the existing NotFound, setSearchParams, and
navigate/report-related mocks to locate and assert these interactions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@frontend/src/__tests__/NotFound.test.jsx`:
- Around line 11-13: The NotFound test mock is inconsistent because NotFound’s
location search and useSearchParams values should reflect the same URL, but the
current pathname/search combination creates a misleading q=abc overlap. Update
the mocked useLocation() search in NotFound.test.jsx to a query string without
q=... (for example, a different param), and adjust the expectation in the
NotFound assertion so it matches the new URL shape used by the component.
- Around line 30-38: The NotFound test suite only covers the query sync
behavior, but it still needs coverage for the other acceptance-criteria CTAs.
Add tests around the NotFound component that verify clicking the Go Back CTA
triggers navigate(-1), and that the Report Broken Link CTA opens the report flow
with the attempted URL passed through as the prefilled value. Use the existing
NotFound, setSearchParams, and navigate/report-related mocks to locate and
assert these interactions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aad1fe1f-45ba-46c9-b4be-2a1a0333c816

📥 Commits

Reviewing files that changed from the base of the PR and between 59fc54f and 4512052.

📒 Files selected for processing (3)
  • frontend/src/__tests__/NotFound.test.jsx
  • frontend/src/pages/NotFound.jsx
  • frontend/vitest-notfound.json
✅ Files skipped from review due to trivial changes (1)
  • frontend/vitest-notfound.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/pages/NotFound.jsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] NotFound.jsx lacks search and 'go back' navigation for confused users

1 participant