Skip to content

⚡ Bolt: Optimize project detail data fetching to remove redundant API call#159

Open
aicoder2009 wants to merge 1 commit into
mainfrom
bolt/optimize-project-lists-fetch-362642379296486606
Open

⚡ Bolt: Optimize project detail data fetching to remove redundant API call#159
aicoder2009 wants to merge 1 commit into
mainfrom
bolt/optimize-project-lists-fetch-362642379296486606

Conversation

@aicoder2009

@aicoder2009 aicoder2009 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

💡 What:
Removed the redundant fetch('/api/projects/${projectId}/lists') network request in src/app/projects/[id]/page.tsx and instead derived the project-specific lists in-memory by filtering the globally fetched allLists response.

🎯 Why:
The frontend was simultaneously fetching a global collection (all user lists via /api/lists) and a subset of that collection (project-specific lists via /api/projects/[id]/lists) using Promise.all. This resulted in a redundant API request and duplicate backend query.

📊 Impact:

  • Reduces the number of outgoing HTTP requests on the project detail page from 3 to 2.
  • Eliminates a redundant database query (fetching user lists and filtering by project, which /api/lists already retrieves).
  • Decreases load time and server resource consumption slightly by relying on in-memory JavaScript array filtering.

🔬 Measurement:

  1. Load a project detail page (e.g., /projects/[id]).
  2. Observe the Network tab in DevTools.
  3. Verify that /api/lists is called, but /api/projects/[id]/lists is no longer called, while all lists still render correctly under the project.

PR created automatically by Jules for task 362642379296486606 started by @aicoder2009

Summary by CodeRabbit

  • Documentation

    • Added new documentation describing efficient data-fetching patterns for concurrent data needs.
  • Refactor

    • Improved performance on project detail pages by optimizing how lists are fetched and processed.

Co-authored-by: aicoder2009 <127642633+aicoder2009@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings June 10, 2026 08:44
@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
opencitation Ready Ready Preview, Comment Jun 10, 2026 8:45am

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR optimizes the project page's data-fetching strategy by fetching the full lists dataset once and deriving project-specific lists through in-memory filtering. The implementation removes redundant API requests and updates the fetch orchestration accordingly.

Changes

In-Memory List Filtering Pattern

Layer / File(s) Summary
Concurrent fetch and in-memory filtering
.jules/bolt.md, src/app/projects/[id]/page.tsx
Documents and implements a pattern where fetchProjectAndLists fetches the project and all lists in parallel, then filters allLists in-memory by projectId to derive the project's subset lists, eliminating the separate backend request for project-specific lists.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A rabbit's fetch was once too slow,
With two requests for all to know,
But now one filter, swift and clean,
Brings parallel joy to the in-memory scene! 🐰✨

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: removing a redundant API call to optimize project detail data fetching. It accurately reflects the primary objective of the PR.
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.

✏️ 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 bolt/optimize-project-lists-fetch-362642379296486606

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/app/projects/[id]/page.tsx (2)

209-212: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Update allLists when adding a list to the project.

After the backend associates the list with the project (line 203), the frontend updates lists (line 211) but does not update the corresponding entry in allLists. This leaves allLists stale — it still contains the old version without the updated projectId. As a result, availableLists (line 231-234) incorrectly continues to include the list even though it now belongs to the project, causing it to appear in both the "available to add" and "currently in project" states.

🔄 Proposed fix to maintain state consistency
       if (result.success) {
-        const addedList = allLists.find((l) => l.id === listId);
-        if (addedList) {
-          setLists((prev) => [...prev, { ...addedList, projectId }]);
-        }
+        setLists((prev) => {
+          const addedList = allLists.find((l) => l.id === listId);
+          return addedList ? [...prev, { ...addedList, projectId }] : prev;
+        });
+        setAllLists((prev) =>
+          prev.map((l) => (l.id === listId ? { ...l, projectId } : l))
+        );
         posthog.capture("list_added_to_project", { project_id: projectId });
🤖 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 `@src/app/projects/`[id]/page.tsx around lines 209 - 212, The frontend updates
lists after associating a list with a project but leaves allLists stale; when
you handle the addedList (found via addedList or listId) and call setLists, also
update allLists immutably (e.g., in setAllLists) so the entry with id === listId
gets its projectId set to projectId; locate the block around addedList/listId
and setLists and add a corresponding setAllLists(prev => prev.map(l => l.id ===
listId ? { ...l, projectId } : l)) to keep availableLists and allLists
consistent.

187-187: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Update allLists when removing a list from the project.

After the backend updates the list's projectId to null (line 181), the frontend removes the list from lists (line 187) but does not update allLists to reflect the change. This causes availableLists (line 231-234) to remain stale — it won't include the removed list because allLists still contains the old version with projectId === projectId. Users cannot immediately re-add the removed list without refreshing the page.

🔄 Proposed fix to maintain state consistency
       if (result.success) {
         setLists((prev) => prev.filter((l) => l.id !== listId));
+        setAllLists((prev) =>
+          prev.map((l) => (l.id === listId ? { ...l, projectId: undefined } : l))
+        );
         posthog.capture("list_removed_from_project", { project_id: projectId });
🤖 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 `@src/app/projects/`[id]/page.tsx at line 187, The frontend removes the list
from lists via setLists((prev) => prev.filter((l) => l.id !== listId)) but never
updates allLists, so availableLists (computed from allLists) stays stale; after
the backend clears the list's projectId, update allLists as well (e.g., in the
same success handler that uses listId and projectId) by mapping over allLists
and setting projectId = null for the matching listId (or replacing that list
with the returned/updated list), so availableLists will include the removed list
immediately; ensure this update happens alongside setLists and uses the same
listId/projectId identifiers (allLists, setAllLists, availableLists).
🤖 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.

Outside diff comments:
In `@src/app/projects/`[id]/page.tsx:
- Around line 209-212: The frontend updates lists after associating a list with
a project but leaves allLists stale; when you handle the addedList (found via
addedList or listId) and call setLists, also update allLists immutably (e.g., in
setAllLists) so the entry with id === listId gets its projectId set to
projectId; locate the block around addedList/listId and setLists and add a
corresponding setAllLists(prev => prev.map(l => l.id === listId ? { ...l,
projectId } : l)) to keep availableLists and allLists consistent.
- Line 187: The frontend removes the list from lists via setLists((prev) =>
prev.filter((l) => l.id !== listId)) but never updates allLists, so
availableLists (computed from allLists) stays stale; after the backend clears
the list's projectId, update allLists as well (e.g., in the same success handler
that uses listId and projectId) by mapping over allLists and setting projectId =
null for the matching listId (or replacing that list with the returned/updated
list), so availableLists will include the removed list immediately; ensure this
update happens alongside setLists and uses the same listId/projectId identifiers
(allLists, setAllLists, availableLists).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: daa02fcc-3497-4fcd-81ff-242df5859f15

📥 Commits

Reviewing files that changed from the base of the PR and between b69285b and cf12f71.

📒 Files selected for processing (2)
  • .jules/bolt.md
  • src/app/projects/[id]/page.tsx

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