Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@

**Learning:** Using `Object.entries(obj).find(([key]) => key === target)` creates O(N) array allocations for the entries and traverses them linearly just to do a simple property lookup. This adds unnecessary memory allocation overhead and Garbage Collection.
**Action:** Use direct property lookup instead: `Object.prototype.hasOwnProperty.call(obj, target) ? obj[target as keyof typeof obj] : undefined`. This maintains O(1) performance while satisfying `security/detect-object-injection` linting rules.

## 2026-10-25 - Avoid flatMap().find() in large arrays

**Learning:** When searching for an item based on properties of nested arrays, using `array.flatMap(mapFn).find(findFn)` creates large intermediate arrays and unnecessarily traverses all elements, causing memory bloat and garbage collection overhead, especially in data-heavy operations like `generateStaticParams`.
**Action:** Use nested `for...of` loops, or `.find()` with `.some()` internally (e.g. `array.find(item => item.children.some(condition))`) to immutably locate the parent element without full flat mapping, then extract the required nested value.
16 changes: 11 additions & 5 deletions app/2026/tags/[tag]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ export async function generateMetadata({ params }: { params: Promise<{ tag: stri

const sessionGroups = await getTalks(year);
const allTalks = sessionGroups.flatMap((group) => group.sessions);
const displayTag =
allTalks.flatMap(getTagsFromTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === decodedTag.toLowerCase()) ?? decodedTag.replaceAll("-", " ");
const targetTag = decodedTag.toLowerCase();
const matchedTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag));
const displayTag = matchedTalk
? (getTagsFromTalk(matchedTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag) ?? decodedTag.replaceAll("-", " "))
: decodedTag.replaceAll("-", " ");

return {
title: `Talks tagged "${displayTag}" - DevBcn ${year}`,
Expand All @@ -58,13 +61,16 @@ export default async function Page({ params }: { params: Promise<{ tag: string }
const sessionGroups = await getTalks(year);
const allTalks = sessionGroups.flatMap((group) => group.sessions);

const displayTag =
allTalks.flatMap(getTagsFromTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === decodedTag.toLowerCase()) ?? decodedTag.replaceAll("-", " ");
const targetTag = decodedTag.toLowerCase();
const matchedTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag));
const displayTag = matchedTalk
? (getTagsFromTalk(matchedTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag) ?? decodedTag.replaceAll("-", " "))
: decodedTag.replaceAll("-", " ");

const filteredTalks = allTalks.filter((talk) => {
const talkTags = getTagsFromTalk(talk);

return talkTags.some((t) => t.replaceAll(" ", "-").toLowerCase() === decodedTag.toLowerCase());
return talkTags.some((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag);
});

if (filteredTalks.length === 0) {
Expand Down
16 changes: 11 additions & 5 deletions app/[year]/tags/[tag]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ export async function generateMetadata({ params }: Readonly<TagPageProps>): Prom

const sessionGroups = await getTalks(year);
const allTalks = sessionGroups.flatMap((group) => group.sessions);
const displayTag =
allTalks.flatMap(getTagsFromTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === decodedTag.toLowerCase()) ?? decodedTag.replaceAll("-", " ");
const targetTag = decodedTag.toLowerCase();
const matchedTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag));
const displayTag = matchedTalk
? (getTagsFromTalk(matchedTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag) ?? decodedTag.replaceAll("-", " "))
: decodedTag.replaceAll("-", " ");
Comment on lines +50 to +54

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Redundant tag re-parsing 🐞 Bug ➹ Performance

The new matchedTalk/displayTag logic parses the matched talk’s tags twice (some(...) during
matchedTalk search, then again with find(...) for displayTag). This duplicates split/trim work
(and the page render parses tags again during filtering), reducing the net allocation savings from
the optimization.
Agent Prompt
## Issue description
`displayTag` determination re-calls `getTagsFromTalk()` after already identifying a match via `getTagsFromTalk(talk).some(...)`, causing redundant parsing/allocations.

## Issue Context
`getTagsFromTalk()` splits and trims the raw tag string on every call, so repeated calls re-allocate arrays/strings.

## Fix Focus Areas
- app/[year]/tags/[tag]/page.tsx[50-54]
- app/[year]/tags/[tag]/page.tsx[70-74]
- app/2026/tags/[tag]/page.tsx[43-47]
- app/2026/tags/[tag]/page.tsx[64-68]

## Suggested fix
Refactor to compute the matching *display tag* in the same pass that finds the match, so the matched talk’s tags are only parsed once.

Example approach:
- Use a small `for...of` search that returns the matching tag string (e.g., `matchedDisplayTag`) instead of `matchedTalk`.
- Or, while filtering talks, set `displayTag` the first time a match is found (and reuse that value for metadata/title).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


return {
title: `Talks tagged "${displayTag}" - DevBcn ${year}`,
Expand All @@ -64,13 +67,16 @@ export default async function TagPage({ params }: Readonly<TagPageProps>) {
const sessionGroups = await getTalks(year);
const allTalks = sessionGroups.flatMap((group) => group.sessions);

const displayTag =
allTalks.flatMap(getTagsFromTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === decodedTag.toLowerCase()) ?? decodedTag.replaceAll("-", " ");
const targetTag = decodedTag.toLowerCase();
const matchedTalk = allTalks.find((talk) => getTagsFromTalk(talk).some((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag));
const displayTag = matchedTalk
? (getTagsFromTalk(matchedTalk).find((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag) ?? decodedTag.replaceAll("-", " "))
: decodedTag.replaceAll("-", " ");

const filteredTalks = allTalks.filter((talk) => {
const talkTags = getTagsFromTalk(talk);

return talkTags.some((t) => t.replaceAll(" ", "-").toLowerCase() === decodedTag.toLowerCase());
return talkTags.some((t) => t.replaceAll(" ", "-").toLowerCase() === targetTag);
});

if (filteredTalks.length === 0) {
Expand Down
Loading