Notes

Thoughts and sketches.

    As Whimsical has grown, the UI has become more complex. Early decisions to have large, airy layouts have led to it now feeling cramped — especially on smaller screens.

    Comparison of sidebar designs
    Comparison of sidebar designs

    I’ve been exploring ways to put the UI on a diet. This includes using space better, lightening the UI font weight, and redrawing the icons.

    Sample icons
    Sample icons

    Figuring out keyboard shortcuts is one of the design details that’s so hard to prototype in Figma. It’s one thing to choose available combinations, but it’s another to consider the ergonomics of where characters live on the keyboard.

    Using V0 made it easy to spin up a prototype and test out different combinations for content folding, a feature we’re working on at Whimsical.

    The visual details aren’t important here. In fact, it’s all fake content and design that was generated by the model. What’s important is getting a feel for what’s right.

    Last week, as a cooldown project between cycles, I started building a prototype for Whimsical mobile companion app. This would be oriented around Tasks and Notifications, though in the future it would expand to access all files.

    To build this, I relied on Claude Code. Here’s my approach:

    • Own the architecture - I prefer to manually build out the layout, styling, and animation. As a designer, I don’t want to outsource these details or leave them to chance. Plus, nuanced visual changes are often too hard to describe to an LLM. I’ve tried the Figma MCP, but it doesn’t reliably produce the results I want.

    • Break it down - As I’m scaffolding things, I’m intentional about breaking things down into components. Beyond maintainability and readability, it allows me to prompt LLMs with explicit, unambiguous names for things. Referring to an <ArchiveButton /> is more reliable than “archive button,” which is not always greppable. Aria labels help here too, especially for icon buttons.

    • Codify components - Use a design system. More than ever, codified design systems are essential for steering LLMs toward desired output. They also help with maintainability, which is something easy to forget when vibe coding. I add instructions to prefer reusing these components to my CLAUDE.md file.

    • Small, detailed prompts - I write prompts for small, specific changes. I’m far more successful with prompts like “Extract the notification loading and filtering into a NotificationProvider component” than “Make an inbox view.” The former is less open to interpretation, while the latter could result in very unexpected outcomes. Predictably, using engineering concepts and terms works better.

    • Plan and act - For big changes, I hash out requirements with the LLM and send the output to a SPECS.md file. With this file, I ask the LLM to break down specs into tasks, which are persisted to a TODO.md. From here, I work through each task individually, committing when each change is complete.

    I’m sure this process will evolve, but for now it works pretty well.

    One of HashiCorp’s principles is “Workflow over technology.” The idea is that technology is volatile but workflows are durable. As a product person, the implication is to understand and design for the underlying workflow and let technology be fungible.

    So in light of agentic AI, I’m wondering “What aspects of building software won’t change?” Maybe those are the things we need to be building around.

    Off the top of my head, I think people will still need to:

    • Prioritize what to work on
    • Balance resource constraints
    • Collaborate with other people
    • Judge when something is done

    Quick little project for today. We often use popovers for calendar controls, but rarely for numeric fields. On occasion, it might be helpful to summon a calculator, so here’s a popover that can do math.

    • If you press the calendar button, the calculator appears in a portaled popover.
    • The expression entered is displayed until you press =.
    • After that, the value is passed back to the input and the popover is dismissed.
    • If the field has a value already, that value is passed into the calculator as the first value in the expression.
    • Buttons are bound to keys, so you can type instead of clicking.

    H/T to Shapr3D, which uses a similar pattern. Their version is much more robust, but the concept is the same. Live demo here.