Back to Blog · Software Architecture

Semiotics of a Desktop Trading App: Why I Hand-Picked Every Icon in Trading Bridge

26 Lucide icons, 7 navigation items, and a dark theme built on amber. How icon choice shapes the feel of a desktop trading application.

MF
Martin Fournier
· June 14, 2026 · 6 MIN READ
Illustration for: Don't Let AI Pick Your Icons: How One Conversation Saved My Trading App From Ugliness

When I asked Claude to build a desktop trading app, it picked icons that looked like they belonged in a 2012 Android settings menu. Material Icons. Filled. Gray. Every button shouting "I was generated by an LLM."

The app worked. The code compiled. But the UI had no taste.

I fixed it with one sentence: "Use Lucide icons."

What happened next surprised me. Claude went through every screen and picked the right icon for every purpose. Not randomly. Not safely. Correctly.

The Ugly Default

I did not screenshot the original. But you know the look. Generic SVG placeholders. Material Icons at 24px with no color context. A settings gear for everything. The same icon repeated across three screens because the AI defaulted to the most generic option it knew.

This is not the AI's fault. LLMs are trained on the web, and the web is full of Material Icons documentation. When you say "add an icon," the safest guess is settings or menu or home. The model optimizes for correctness (it will render), not aesthetics (it will look good).

The fix is not to hand-pick every icon yourself. The fix is to set constraints.

One Sentence, 26 Icons

I told Claude: "Use Lucide icons."

That is a curated library. Consistent stroke width (1.25px for the small ones). Designed for 16-24px rendering. Community maintained as a fork of Feather. Every icon has a clear semantic boundary: Cpu is not Monitor, Radio is not Wifi.

Claude took it from there. Here is what it chose.

Sidebar

Six navigation items, six Lucide icons. I did not pick a single one.

Screen Icon Chosen Why It Works
Dashboard LayoutDashboard Not a chart. Not a house. A grid of widgets -- the icon communicates "many things in one place."
Data Manager Database Data lives in a database. Literally a cylinder icon. No ambiguity.
Strategies Cpu Strategies compile and execute. They are computational entities. A chip conveys this better than a book or a list.
Live Room Radio Live trading streams ticks from the broker. A radio tower icon captures broadcast better than a dollar sign or a chart.
Compare GitCompare Side-by-side strategy comparison. The branching arrows mirror git diff -- two states, one view.
Backtests Clock Runs are chronological. A clock says "history" without needing a list or a document icon.

Each choice maps to a real concept. Not decorative. Not generic.

Status Bar

Four states, four icons. Again, Claude chose them.

Signal Icon Meaning
Error AlertTriangle A triangle. Instantly read at 14px.
Warning Zap A lightning bolt. Energy. Caution.
Success CheckCircle A checkmark in a circle. Confirmation.
Info Info A lowercase 'i'. Universal.

The UTC clock companion icon is Clock. The connection indicator is Radio (same as the sidebar Live Room). Consistency across screens -- Claude did not need to be told.

Backtest Results

This is the densest screen. Ten inline icons. Claude laid them out without me specifying a single one.

  • Search for the text input
  • Filter for the filter panel toggle
  • ArrowUpDown for sort direction
  • RefreshCw for re-fetching data
  • Trash2 for deleting runs
  • DollarSign for PnL columns
  • Percent for return and win rate
  • Activity for trade count and volatility
  • ExternalLink for external reports
  • ChevronRight for expanding rows

Every icon makes sense. Not one is a generic placeholder.

Charts

The Parameter Sensitivity Heatmap and Pareto Frontier chart each have empty states. Claude chose:

  • Sliders for the heatmap (parameters are adjustable values)
  • GitBranch for the Pareto frontier (strategies branch into tradeoffs)
  • Info for the Pareto tooltip (one sentence of explanation)

Dashboard

One icon. Key. Next to the "Manage API Keys" button. Not Settings. Not Lock. Key. Correct.

Strategy Cards

Zero icons. Just Unicode triangles for expand and collapse.

Claude decided that cards already have visual weight and adding icons would create noise. It was right. I did not tell it to skip icons.

Why This Worked

I gave the AI one constraint: "Use Lucide icons." It selected 26 unique icons across 7 components. Every one was contextually correct.

Three things made this possible.

A well-designed icon library. Lucide has clear boundaries between similar concepts. LayoutDashboard is not Grid. Activity is not Zap. GitCompare is not Shuffle. The AI can disambiguate because the library is disambiguated.

Consistent visual language. Every Lucide icon has the same stroke width, the same corner radius, the same padding. The AI does not need to worry about mixing filled and outlined styles (Material Icons) or 12px vs 24px variants (Font Awesome). It just imports the component and passes a class.

Tree-shakeable imports. @lucide/vue lets you import only what you use. Claude wrote:

import { LayoutDashboard, Database, Cpu } from '@lucide/vue'

If it imported a wrong icon, I could swap it by changing one import line. No bundle bloat.

The Collaboration Pattern

This is my preferred way to work with AI on UI:

  1. Human picks the palette. Not colors. Icon library, font family, spacing scale. The human provides taste.

  2. AI fills in the details. Which icon for which button, which font weight for which heading, which spacing for which component.

  3. Human reviews. Quick scan for wrong metaphors. Swap the one or two that miss.

  4. Done.

Without step one, the AI fills every slot with Material Icons or inline SVGs. The app compiles. The user sees something that looks generated.

Not wrong. Ugly.

With step one, the same AI produces a UI that looks intentional. A trader opening the app sees a Radio icon in the sidebar and immediately understands: this screen connects to a live broker. They do not need to read a label.

The Full Inventory

26 Lucide icons, 7 components, 18 Vue files:

Activity       AlertTriangle  ArrowUpDown
CheckCircle    ChevronRight   Clock
Cpu            Database       DollarSign
ExternalLink   Filter         GitBranch
GitCompare     Info           Key
LayoutDashboard LogOut       Percent
Radio          RefreshCw     Search
Sliders        Trash2        TrendingUp
X              Zap

Plus three Unicode characters used where icons would add weight instead of clarity: , , ×.

The AI picked all of them. I told it to use Lucide. It did the rest.


Built with Electron 33, Vue 3.5, Vite 6, and @lucide/vue 1.17. Source code at github.com/martinfou/trading-bridge.