Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@
## 2024-05-18 - Concurrent Fetching with Owner IDs in Share Links
**Learning:** In the share system, endpoints processing a share code typically suffer from waterfall latency by first loading target entity details (like a project) and then querying its associated elements (like project lists) using the entity's owner ID (`userId`). However, the `shareLink` object already contains the `userId` field (representing the owner's ID).
**Action:** Always leverage the existing owner's ID within `shareLink` to bypass sequential dependencies and fetch parent entities (like projects) concurrently with their child elements (like user lists) using `Promise.all`.

## 2024-05-18 - Avoiding Duplicate Queries via In-Memory Derivation
**Learning:** React components sometimes fetch a global collection (like all user lists) and a specific subset (like lists for a single project) simultaneously. Making redundant backend requests for the subset causes unnecessary network overhead.
**Action:** When a global collection and its subset are needed on the frontend concurrently, always fetch the global collection once and derive the subset in-memory using `Array.prototype.filter`, avoiding the redundant backend query.

## 2024-05-18 - Rejected Workaround for React Hooks Warnings
**Learning:** Wrapping `setState` in `setTimeout`, `Promise.resolve().then()`, or prepending `await Promise.resolve()` to silence ESLint warnings about synchronous `setState` in `useEffect` are critical anti-patterns that delay state updates artificially and create potential memory leaks.
**Action:** Never use `setTimeout` or extraneous promise resolutions to circumvent `react-hooks/set-state-in-effect`. Standard state updates within `useEffect` are safe when properly managed.
14 changes: 6 additions & 8 deletions src/app/projects/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ export default function ProjectDetailPage({ params }: { params: Promise<{ id: st
// OPTIMIZATION: Execute independent network requests and JSON parsing concurrently
// using Promise.all. This prevents a 3-step waterfall, reducing Time to First Byte
// (TTFB) and overall load time significantly on this detail page.
const [projectRes, listsRes, allListsRes] = await Promise.all([
// BOLT OPTIMIZATION: We avoid a redundant backend query by deriving the project lists
// in-memory from the global lists array, instead of fetching them separately.
const [projectRes, allListsRes] = await Promise.all([
fetch(`/api/projects/${projectId}`),
fetch(`/api/projects/${projectId}/lists`),
fetch("/api/lists"),
]);

const [projectResult, listsResult, allListsResult] = await Promise.all([
const [projectResult, allListsResult] = await Promise.all([
projectRes.json(),
listsRes.json(),
allListsRes.json(),
]);

Expand All @@ -81,12 +81,10 @@ export default function ProjectDetailPage({ params }: { params: Promise<{ id: st
setEditName(projectResult.data.name);
setEditDescription(projectResult.data.description || "");

if (listsResult.success) {
setLists(listsResult.data);
}

if (allListsResult.success) {
setAllLists(allListsResult.data);
// Derive project-specific lists from all lists
setLists(allListsResult.data.filter((list: List) => list.projectId === projectId));
Comment on lines 84 to +87

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don't silently treat /api/lists failures as “this project has no lists”.

src/app/api/lists/route.ts:6-31 returns { success: false, error } for 401/500 cases. With this branch, those failures now fall through to an empty lists state, so the page can render 0 lists even when the project actually has lists. Please surface the failure or fall back to the project-specific fetch instead of downgrading partial fetch failures to an empty subset.

🤖 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 84 - 87, The project page in the
lists-loading flow is treating a failed /api/lists response as an empty project
list, which can incorrectly show “0 lists” on auth/server errors. Update the
logic in the project page component around the all-lists fetch (the branch that
calls setAllLists and filters into setLists) to detect allListsResult.success
=== false and either surface that error state or fall back to a project-specific
fetch instead of filtering an empty subset. Keep the fix localized to the
lists-loading path in the page component and preserve the existing
projectId-based filtering only for successful responses.

}
} catch (err) {
console.error("Error fetching project:", err);
Expand Down
Loading