Skip to content

Expose Exhibition under /exhibition + mobile navigation#281

Merged
dmnktoe merged 6 commits intomainfrom
cursor/exhibition-rewrites-mobile-nav-5777
Apr 23, 2026
Merged

Expose Exhibition under /exhibition + mobile navigation#281
dmnktoe merged 6 commits intomainfrom
cursor/exhibition-rewrites-mobile-nav-5777

Conversation

@dmnktoe
Copy link
Copy Markdown
Owner

@dmnktoe dmnktoe commented Apr 23, 2026

Adds Vercel rewrites to serve the exhibition app under /exhibition/ and updates the header navigation to include an “Exhibition” link with a mobile-friendly hamburger menu.

  • Adds vercel.json rewrites for /exhibition -> https://sentiment-exhibition.vercel.app/
  • Adds “Exhibition” to nav
  • Mobile navigation: toggle button + dropdown, a11y attributes
  • Fixes repo lint script (Next.js CLI no longer provides next lint here), so pnpm lint works again
  • Adds rewrite for /public/* to the exhibition app to avoid 404s when the embedded app requests assets with /public/...
  • Adds rewrites for /api/events* to proxy the exhibition events endpoint (handles missing trailing slash)
  • Fixes mobile dropdown being clipped by removing overflow-hidden on the header pill container
  • Closes mobile menu on link click, Escape, and outside-click

Verification:

  • pnpm lint
  • pnpm test

Co-authored-by: Domenik Töfflinger <dmnktoe@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

Switches the lint script to run ESLint over src; converts the header to a client component with mobile navigation state and an added /exhibition/ link plus test coverage; adds vercel.json with rewrite rules for /api/events, /public/:path*, and /exhibition routes.

Changes

Cohort / File(s) Summary
Build Configuration
package.json
Replaced scripts.lint from next lint to eslint src.
Header Component & Tests
src/components/layout/Header.tsx, src/__tests__/components/layout/Header.test.tsx
Made Header a client component ('use client'), added mobileNavOpen state, generated mobileNavId, desktop nav gated by sm:block, added sm:hidden toggle with ARIA attributes, conditional mobile nav rendering, and extended nav links with /exhibition/; updated tests to expect the Exhibition link and increased link/item counts.
Vercel Configuration
vercel.json
Added rewrites routing /api/events variants to https://sentiment-exhibition.vercel.app/api/events/, proxying /public/:path* to the exhibition host, and rewriting /exhibition and /exhibition/:path* to the exhibition domain root.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped into the header light,
Added doors for mobile night,
ESLint watched each little track,
Vercel points the routes right back,
A tiny rabbit cheers the site! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: exposing the Exhibition app under /exhibition and adding mobile navigation to the header.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/exhibition-rewrites-mobile-nav-5777

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 and usage tips.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sentiment Ready Ready Preview, Comment Apr 23, 2026 5:57pm

@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 34.61538% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.77%. Comparing base (b410896) to head (725f39e).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/components/layout/Header.tsx 34.61% 17 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #281      +/-   ##
==========================================
- Coverage   64.77%   63.77%   -1.01%     
==========================================
  Files          67       67              
  Lines         758      784      +26     
  Branches      155      161       +6     
==========================================
+ Hits          491      500       +9     
- Misses        267      284      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dmnktoe dmnktoe marked this pull request as ready for review April 23, 2026 16:53
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/components/layout/Header.tsx (1)

79-85: Duplicate navLinks rendering — desktop Navigation and mobile panel both map the same array with identical markup.

Minor DRY concern. Consider factoring a single <NavList orientation="row|col" /> that both call sites render, so future changes (e.g., adding a link, closing menu on click) happen in one place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/layout/Header.tsx` around lines 79 - 85, Currently both the
desktop Navigation and the mobile panel map navLinks with identical markup (the
ul/li/NavLink pattern), so extract that mapping into a single reusable component
(e.g., create a NavList component) that accepts an orientation prop ("row" |
"col") and an optional onItemClick callback; move the navLinks.map logic into
NavList (rendering a ul with className based on orientation and li
key={link.href} with <NavLink>{link.text}</NavLink>) and replace the duplicated
mapping in both Navigation and the mobile panel with <NavList orientation="row"
/> and <NavList orientation="col" onItemClick={closeMenu} /> (or equivalent) so
link additions and behavior changes happen in one place.
vercel.json (1)

4-14: Collapse the three rewrites for /api/events into one.

:path* matches zero segments, so /api/events/:path* already covers both /api/events and /api/events/. Remove the first two entries.

Suggested diff
-    {
-      "source": "/api/events",
-      "destination": "https://sentiment-exhibition.vercel.app/api/events/"
-    },
-    {
-      "source": "/api/events/",
-      "destination": "https://sentiment-exhibition.vercel.app/api/events/"
-    },
     {
       "source": "/api/events/:path*",
       "destination": "https://sentiment-exhibition.vercel.app/api/events/:path*"
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vercel.json` around lines 4 - 14, Remove the redundant rewrite rules for
"/api/events" and "/api/events/" and keep only the rule with source
"/api/events/:path*" pointing to
"https://sentiment-exhibition.vercel.app/api/events/:path*"; specifically delete
the entries whose source is "/api/events" and "/api/events/" so that the single
rule with source "/api/events/:path*" (which matches zero or more segments)
handles all three cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/layout/Header.tsx`:
- Line 15: Update the navLinks entry for Exhibition to remove the trailing slash
so it matches other entries and the test expectation: change the object in the
navLinks array (the entry with text 'Exhibition') from href: '/exhibition/' to
href: '/exhibition'; this keeps NavLink's active-state logic
(pathname.startsWith(href)) consistent with the canonical URL and satisfies
Header.test.tsx's assertion that href === '/exhibition'.
- Around line 70-87: The mobile menu (controlled by mobileNavOpen in Header)
never closes on navigation or Escape/outside clicks; update Header so the menu
closes when a nav item is activated and on Escape/outside-click: add a click
handler to NavLink (or pass an onNavigate callback) that sets
mobileNavOpen=false when a link is clicked, and add keyboard/document listeners
in Header to close the menu on "Escape" and a mousedown/touchstart handler that
closes when clicks happen outside the element with id mobileNavId; ensure to
cleanup listeners on unmount and/or when mobileNavOpen changes.

In `@vercel.json`:
- Around line 2-31: The rewrites currently cause relative asset requests like
/exhibition/public/... to miss the /public/:path* rule; either update the
exhibition app to use absolute asset URLs (/public/...) and keep the existing
/public/:path* rewrite, or add a specific rewrite mapping
"/exhibition/public/:path*" ->
"https://sentiment-exhibition.vercel.app/public/:path*" (or otherwise ensure
"/exhibition/:path*" correctly strips the /exhibition prefix) so assets
requested under /exhibition/public/* are forwarded to the exhibition origin.

---

Nitpick comments:
In `@src/components/layout/Header.tsx`:
- Around line 79-85: Currently both the desktop Navigation and the mobile panel
map navLinks with identical markup (the ul/li/NavLink pattern), so extract that
mapping into a single reusable component (e.g., create a NavList component) that
accepts an orientation prop ("row" | "col") and an optional onItemClick
callback; move the navLinks.map logic into NavList (rendering a ul with
className based on orientation and li key={link.href} with
<NavLink>{link.text}</NavLink>) and replace the duplicated mapping in both
Navigation and the mobile panel with <NavList orientation="row" /> and <NavList
orientation="col" onItemClick={closeMenu} /> (or equivalent) so link additions
and behavior changes happen in one place.

In `@vercel.json`:
- Around line 4-14: Remove the redundant rewrite rules for "/api/events" and
"/api/events/" and keep only the rule with source "/api/events/:path*" pointing
to "https://sentiment-exhibition.vercel.app/api/events/:path*"; specifically
delete the entries whose source is "/api/events" and "/api/events/" so that the
single rule with source "/api/events/:path*" (which matches zero or more
segments) handles all three cases.
🪄 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: ef74d549-0617-4d50-9544-7d3b47319da3

📥 Commits

Reviewing files that changed from the base of the PR and between 9fb69df and d258f98.

📒 Files selected for processing (4)
  • package.json
  • src/__tests__/components/layout/Header.test.tsx
  • src/components/layout/Header.tsx
  • vercel.json

Comment thread src/components/layout/Header.tsx Outdated
Comment thread src/components/layout/Header.tsx
Comment thread vercel.json
Comment on lines +2 to +31
"rewrites": [
{
"source": "/api/events",
"destination": "https://sentiment-exhibition.vercel.app/api/events/"
},
{
"source": "/api/events/",
"destination": "https://sentiment-exhibition.vercel.app/api/events/"
},
{
"source": "/api/events/:path*",
"destination": "https://sentiment-exhibition.vercel.app/api/events/:path*"
},
{
"source": "/public/:path*",
"destination": "https://sentiment-exhibition.vercel.app/public/:path*"
},
{
"source": "/exhibition",
"destination": "https://sentiment-exhibition.vercel.app/"
},
{
"source": "/exhibition/",
"destination": "https://sentiment-exhibition.vercel.app/"
},
{
"source": "/exhibition/:path*",
"destination": "https://sentiment-exhibition.vercel.app/:path*"
}
]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the exhibition app serves a Next.js HTML shell referencing /_next/*
curl -s -L https://sentiment-exhibition.vercel.app/ | grep -oE '"/_next/[^"]+"|href="/[^"]+"|src="/[^"]+"' | sort -u | head -40

Repository: dmnktoe/sentiment

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Get response headers and first part of HTML to identify the app type
curl -s -I https://sentiment-exhibition.vercel.app/ | head -20
echo "---"
curl -s https://sentiment-exhibition.vercel.app/ | head -100

Repository: dmnktoe/sentiment

Length of output: 5142


🏁 Script executed:

#!/bin/bash
# Check if the domain is accessible and what it serves
curl -s -w "\nHTTP Status: %{http_code}\n" https://sentiment-exhibition.vercel.app/ | head -150

Repository: dmnktoe/sentiment

Length of output: 6606


Relative asset paths in the exhibition app will 404 under the current rewrites.

The exhibition app at sentiment-exhibition.vercel.app is a static/traditional website (not Next.js) that references assets via relative paths: public/css/main.css, public/img/logo.svg, public/img/stage-video.mp4, etc.

When served via /exhibition, the browser URL remains /exhibition, so relative asset paths resolve to /exhibition/public/css/main.css, /exhibition/public/img/logo.svg, etc. These do not match the /public/:path* rewrite (which only catches /public/* at the root), causing assets to 404 or serve from the wrong origin.

Either:

  • Reconfigure the exhibition app to use absolute paths (/public/...) instead of relative paths, then ensure the /public/:path* rewrite is in place (it already is), or
  • Restructure the rewrite rules to handle /exhibition/:path*sentiment-exhibition.vercel.app/:path* to preserve all sub-paths including /exhibition/public/*.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vercel.json` around lines 2 - 31, The rewrites currently cause relative asset
requests like /exhibition/public/... to miss the /public/:path* rule; either
update the exhibition app to use absolute asset URLs (/public/...) and keep the
existing /public/:path* rewrite, or add a specific rewrite mapping
"/exhibition/public/:path*" ->
"https://sentiment-exhibition.vercel.app/public/:path*" (or otherwise ensure
"/exhibition/:path*" correctly strips the /exhibition prefix) so assets
requested under /exhibition/public/* are forwarded to the exhibition origin.

@dmnktoe dmnktoe merged commit eedb645 into main Apr 23, 2026
6 checks passed
@dmnktoe dmnktoe deleted the cursor/exhibition-rewrites-mobile-nav-5777 branch April 23, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants