Skip to content

Commit f9df6ac

Browse files
perf: memoize static configuration in Apps component
* Moved CATEGORIES and apps arrays outside of Apps component * Reduces unnecessary memory allocations on every render * Ensures downstream useMemo dependencies are stable * Followed Bolt optimization guidelines and added explanatory comments Co-authored-by: Oxygen-Low <95589118+Oxygen-Low@users.noreply.github.com>
1 parent 353a85c commit f9df6ac

3 files changed

Lines changed: 5626 additions & 3244 deletions

File tree

.jules/bolt.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## 2024-05-24 - [Avoid recreating static JSX arrays]
2+
3+
**Learning:** Static arrays that contain JSX elements (e.g. configuring categories or routing with icons) created inside a React component render function are re-allocated on every single render. This forces child components and `useMemo` hooks depending on them to constantly re-evaluate.
4+
**Action:** Always define static configuration structures containing JSX elements outside the component body.

client/pages/Apps.tsx

Lines changed: 114 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -44,119 +44,124 @@ interface AppMetadata {
4444
component: React.ComponentType;
4545
}
4646

47+
/**
48+
* ⚡ Bolt Performance Optimization:
49+
* Moved static configurations (`CATEGORIES` and `apps`) outside of the `Apps` component body.
50+
* This prevents the recreation of these large arrays (and their internal JSX elements) on every render,
51+
* saving memory allocations and preventing unnecessary recalculations in downstream useMemo hooks.
52+
*/
53+
const CATEGORIES: {
54+
name: Category;
55+
label: string;
56+
icon: React.ReactNode;
57+
description: string;
58+
}[] = [
59+
{
60+
name: "All",
61+
label: "All",
62+
icon: <Box className="w-5 h-5" />,
63+
description: "All available applications",
64+
},
65+
{
66+
name: "Utility",
67+
label: "Utility",
68+
icon: <Wrench className="w-5 h-5" />,
69+
description: "Tools and utilities",
70+
},
71+
{
72+
name: "LLM/AI",
73+
label: "LLM/AI",
74+
icon: <BrainCircuit className="w-5 h-5" />,
75+
description: "AI powered applications",
76+
},
77+
{
78+
name: "Development",
79+
label: "Development",
80+
icon: <Code className="w-5 h-5" />,
81+
description: "Developer tools",
82+
},
83+
{
84+
name: "Social",
85+
label: "Social",
86+
icon: <MessageSquare className="w-5 h-5" />,
87+
description: "Connect with others",
88+
},
89+
{
90+
name: "Games",
91+
label: "Games",
92+
icon: <Gamepad2 className="w-5 h-5" />,
93+
description: "Fun and games",
94+
},
95+
];
96+
97+
const apps: AppMetadata[] = [
98+
{
99+
id: "chatbot",
100+
name: "Chatbot",
101+
description:
102+
"Chat with state-of-the-art LLMs with memory and custom styles.",
103+
categories: ["All", "LLM/AI"],
104+
icon: <Bot className="w-8 h-8 text-cyan-500" />,
105+
component: ChatbotApp,
106+
},
107+
{
108+
id: "ai-screenshare",
109+
name: "AI Screenshare",
110+
description:
111+
"Let AI watch your screen and react to what you are doing in real-time.",
112+
categories: ["All", "LLM/AI"],
113+
icon: <Monitor className="w-8 h-8 text-cyan-500" />,
114+
component: AiScreenshareApp,
115+
},
116+
{
117+
id: "llm-model-finder",
118+
name: "LLM Model Finder",
119+
description:
120+
"Find the best model capable of running on your hardware for different tasks.",
121+
categories: ["All", "LLM/AI"],
122+
icon: <Search className="w-8 h-8 text-cyan-500" />,
123+
component: LlmModelFinderApp,
124+
},
125+
{
126+
id: "repositories",
127+
name: "Repositories",
128+
description:
129+
"Host git repositories with issues, pull requests, and web editing.",
130+
categories: ["All", "Development"],
131+
icon: <GitBranch className="w-8 h-8 text-cyan-500" />,
132+
component: RepositoriesApp,
133+
},
134+
{
135+
id: "file-compressor",
136+
name: "File Compressor",
137+
description: "Compress images to save storage space.",
138+
categories: ["All", "Utility"],
139+
icon: <Box className="w-8 h-8 text-cyan-500" />,
140+
component: FileCompressorApp,
141+
},
142+
{
143+
id: "oauth",
144+
name: "OAuth",
145+
description:
146+
"Add OAuth to your applications via Oxygen Low's Software Accounts.",
147+
categories: ["All", "Development"],
148+
icon: <ShieldCheck className="w-8 h-8 text-cyan-500" />,
149+
component: OauthApp,
150+
},
151+
{
152+
id: "learn",
153+
name: "Learn",
154+
description: "Master new skills through interactive courses and 3D models.",
155+
categories: ["All", "Utility"],
156+
icon: <BookOpen className="w-8 h-8 text-cyan-500" />,
157+
component: LearnApp,
158+
},
159+
];
160+
47161
export default function Apps() {
48162
const [selectedCategory, setSelectedCategory] = useState<Category>("All");
49163
const [activeApp, setActiveApp] = useState<AppMetadata | null>(null);
50164

51-
const CATEGORIES: {
52-
name: Category;
53-
label: string;
54-
icon: React.ReactNode;
55-
description: string;
56-
}[] = [
57-
{
58-
name: "All",
59-
label: "All",
60-
icon: <Box className="w-5 h-5" />,
61-
description: "All available applications",
62-
},
63-
{
64-
name: "Utility",
65-
label: "Utility",
66-
icon: <Wrench className="w-5 h-5" />,
67-
description: "Tools and utilities",
68-
},
69-
{
70-
name: "LLM/AI",
71-
label: "LLM/AI",
72-
icon: <BrainCircuit className="w-5 h-5" />,
73-
description: "AI powered applications",
74-
},
75-
{
76-
name: "Development",
77-
label: "Development",
78-
icon: <Code className="w-5 h-5" />,
79-
description: "Developer tools",
80-
},
81-
{
82-
name: "Social",
83-
label: "Social",
84-
icon: <MessageSquare className="w-5 h-5" />,
85-
description: "Connect with others",
86-
},
87-
{
88-
name: "Games",
89-
label: "Games",
90-
icon: <Gamepad2 className="w-5 h-5" />,
91-
description: "Fun and games",
92-
},
93-
];
94-
95-
const apps: AppMetadata[] = [
96-
{
97-
id: "chatbot",
98-
name: "Chatbot",
99-
description:
100-
"Chat with state-of-the-art LLMs with memory and custom styles.",
101-
categories: ["All", "LLM/AI"],
102-
icon: <Bot className="w-8 h-8 text-cyan-500" />,
103-
component: ChatbotApp,
104-
},
105-
{
106-
id: "ai-screenshare",
107-
name: "AI Screenshare",
108-
description:
109-
"Let AI watch your screen and react to what you are doing in real-time.",
110-
categories: ["All", "LLM/AI"],
111-
icon: <Monitor className="w-8 h-8 text-cyan-500" />,
112-
component: AiScreenshareApp,
113-
},
114-
{
115-
id: "llm-model-finder",
116-
name: "LLM Model Finder",
117-
description:
118-
"Find the best model capable of running on your hardware for different tasks.",
119-
categories: ["All", "LLM/AI"],
120-
icon: <Search className="w-8 h-8 text-cyan-500" />,
121-
component: LlmModelFinderApp,
122-
},
123-
{
124-
id: "repositories",
125-
name: "Repositories",
126-
description:
127-
"Host git repositories with issues, pull requests, and web editing.",
128-
categories: ["All", "Development"],
129-
icon: <GitBranch className="w-8 h-8 text-cyan-500" />,
130-
component: RepositoriesApp,
131-
},
132-
{
133-
id: "file-compressor",
134-
name: "File Compressor",
135-
description: "Compress images to save storage space.",
136-
categories: ["All", "Utility"],
137-
icon: <Box className="w-8 h-8 text-cyan-500" />,
138-
component: FileCompressorApp,
139-
},
140-
{
141-
id: "oauth",
142-
name: "OAuth",
143-
description:
144-
"Add OAuth to your applications via Oxygen Low's Software Accounts.",
145-
categories: ["All", "Development"],
146-
icon: <ShieldCheck className="w-8 h-8 text-cyan-500" />,
147-
component: OauthApp,
148-
},
149-
{
150-
id: "learn",
151-
name: "Learn",
152-
description:
153-
"Master new skills through interactive courses and 3D models.",
154-
categories: ["All", "Utility"],
155-
icon: <BookOpen className="w-8 h-8 text-cyan-500" />,
156-
component: LearnApp,
157-
},
158-
];
159-
160165
const filteredApps = useMemo(() => {
161166
if (selectedCategory === "All") return apps;
162167
return apps.filter((app) => app.categories.includes(selectedCategory));

0 commit comments

Comments
 (0)