feat: pre-compute developer apps selections in data layer#17180
Merged
Conversation
Move randomization of highlighted apps and category previews from page-level unstable_cache to data-layer (trigger.dev task). Changes: - Add DeveloperToolsDataEnvelope type with appsById lookup + selections - Pre-compute selections (mainPageHighlights, categoryHighlights, categoryPreviews) in trigger.dev task - Remove unstable_cache wrappers from utils.ts, revert unused `every` time util addition - Update page components to use pre-computed selections with O(1) lookups - Transform mock data to envelope format This fixes cache invalidation issues caused by unstable_cache creating unique keys from function arguments (searchParams). Selections now persist daily and are consistent for all users. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
✅ Deploy Preview for ethereumorg ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Move all developer tools fetching logic into a dedicated folder to maintain data layer isolation and prevent bidirectional imports between data layer and app code. Changes: - Create src/data-layer/fetchers/developer-tools/ module with: - index.ts: main fetchDeveloperTools orchestrator - utils.ts: types, constants, and utility functions - fetchBuidlGuidl.ts: BuidlGuidl API fetcher - fetchGitHub.ts: GitHub GraphQL enrichment - fetchNpmJs.ts: npm downloads enrichment - Move envelope types (DeveloperToolsDataEnvelope, DeveloperAppsComputedSelections) from app code to data layer - Keep only UI-specific code in app (getCategoryTagStyle) - Update all imports to use the new module structure This ensures the data layer remains self-contained and doesn't depend on app-level code for runtime functions.
pettinarip
reviewed
Feb 2, 2026
| getMainPageHighlights, | ||
| getRandomPreviewsByCategory, | ||
| transformDeveloperAppsData, | ||
| } from "../../../app/[locale]/developers/apps/utils" |
Member
There was a problem hiding this comment.
I don't like too much this injection from things outside the data-layer. This module should be completely isolated from external code. The fetcher should do its thing and should have all the necessary logic to operate alone.
The fetcher is becoming too fat, logic heavy. Just for move this forward, I'd suggest putting all this logic next to the fetcher (it is logic closer to data fetching than UI).
Created a PR with a proposal for refactor.
…-tools-isolation refactor: isolate developer-tools module in data layer
This was referenced Feb 5, 2026
Merged
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.

Extends
page-developer-appsbranchSummary
unstable_cacheto data-layer (trigger.dev task)DeveloperToolsDataEnvelopetype withappsByIdlookup + pre-computed selectionsunstable_cachewrappers from utils.tsProblem
The previous implementation used
unstable_cacheat the page level, butunstable_cachecreates cache keys from both thekeyPartsarray and functionarguments. Passing the full apps array or searchParams as arguments created unique cache entries for each request, defeating the cache entirely.
Solution
Pre-compute all randomized selections in the trigger.dev task (daily refresh):
mainPageHighlights- 3 apps for landing pagecategoryHighlights- 3 apps per category page (7 categories)categoryPreviews- 5 apps per category card on landing pageStore as an envelope with
appsByIdRecord for O(1) modal lookups.Audit Results
Test plan
?appId=param?tag=param🤖 Generated with Claude Code