Members tab subpaths + homepage search fixes#411
Merged
Conversation
/members, /members/ambassadors and /members/companies are now fully prerendered static routes instead of a client-side ?tab= query param, so hard reloads serve the exact tab HTML with no layout shift. Tab switches are prefetched Link navigations that carry q/sort along. Legacy ?tab= URLs and /companies redirect to the new paths; legacy paginated /members/:n URLs still serve the developers page. Co-authored-by: Lee Robinson <lee@leerob.com>
Fuse is configured with minMatchCharLength: 2, so filtering on the first character always produced an empty result set and flashed the 'No plugins found' state. Keep showing the full leaderboard until the query is at least two characters. Co-authored-by: Lee Robinson <lee@leerob.com>
Search results were re-sorted purely by the active tab metric, so on Trending an exact match like 'Vercel' could rank below fuzzier matches with higher recent install velocity. While a search is active, exact name/slug matches now sort first on every tab (and bypass Trending's has-installs filter so they can't disappear entirely). Co-authored-by: Lee Robinson <lee@leerob.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The [...number] route only existed to serve old paginated URLs (/members/2, ...) the same developers page. A digits-only permanent redirect to /members does the job without an extra route; unknown non-numeric paths now 404 instead of silently rendering the page. Co-authored-by: Lee Robinson <lee@leerob.com>
Every /[slug] redirect page awaited getRuleRedirects(), whose cache
fill runs getPlugins({ fetchAll: true }) — the entire plugins table
with all components, paged serially. With ~3400 of these pages
prerendering concurrently across build workers, waiting on that slow
fill exceeded Next's use-cache prerender timeout and failed the build.
Each page now resolves its own slug with a tiny per-slug cached query
(getRuleRedirectTarget), and generateStaticParams uses a slugs-only
query (getRuleRedirectSlugs) instead of the full-table fetch. Newest
plugin still wins for duplicate rule slugs, matching the old map.
Co-authored-by: Lee Robinson <lee@leerob.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three issues, plus a build failure discovered while deploying this branch:
1. Members page layout shift on hard reload
The Developers / Ambassadors / Companies tabs were a client-side
?tab=query param, so a hard reload on e.g.?tab=companiesfirst served the cached developers HTML and then shifted after hydration./members,/members/ambassadorsand/members/companiesare now dedicated fully prerendered static routes (verified○ Staticin the build output, 5m revalidate), each with its own tab-appropriate initial data (getMembersgained anambassadorsOnlyfilter).<Link>navigations that carry the activeq/sortparams along, so client-side behavior matches the old query-param tabs./members?tab=ambassadors|companies→ the new paths (plus a client-side cleanup of the leftovertabparam),/companies→/members/companies, and old paginated/members/:numberURLs (digits only) →/members— the previous[...number]catch-all route is removed entirely. Footer and sitemap links updated.2. Homepage: empty state on the first typed character
Fuse is configured with
minMatchCharLength: 2, but search mode activated at 1 character — so the first keystroke always rendered "No plugins found". Search mode now requires two characters; until then the full leaderboard stays visible.3. Homepage: exact match not first on Trending
Search results were re-sorted purely by the active tab metric (Trending = 30d install velocity), discarding relevance — searching "Vercel" ranked the exact match ~5th. While a search is active, plugins whose name or slug exactly matches the query are pinned to the top on every tab, and exact matches bypass Trending's has-installs filter so they can't disappear entirely. Non-exact matches keep their tab-metric order.
4. Build:
USE_CACHE_TIMEOUTon/[slug]rule redirect pagesEvery legacy rule redirect page (
/[slug], ~3400 of them) awaitedgetRuleRedirects(), whose cache fill runsgetPlugins({ fetchAll: true })— the whole plugins table with all components, paged serially. With thousands of pages prerendering concurrently across build workers, waiting on that slow fill exceeded Next's use-cache prerender fill timeout and aborted the build.Each page now resolves its own slug via a tiny per-slug cached query (
getRuleRedirectTarget), andgenerateStaticParamsuses a slugs-only query (getRuleRedirectSlugs) instead of the full-table fetch. The newest plugin still wins for duplicate rule slugs, matching the old map-building order.Verification
bun run typecheckandbunx biome ci .pass (CI parity).next buildsucceeds; new members routes are fully static and the prerendered HTML for each route contains the correct tab state (correct placeholder, active tab, content)./members?tab=companies→/members/companies(307, preservesq/sort),/companies→/members/companies(308),/members/2and/members/15→/members(308),/members/ambassadorsand/members/companies→ 200,/members/not-a-number→ 404.USE_CACHE_TIMEOUTfix was validated structurally (build passes with the new query/page code); the real fix is that redirect pages no longer wait on the full-table plugins cache fill.