← Home

Case study / personal website

How to build a button.

A small design problem inside a prepared system: context, judgment, live prototypes, and the decision to define a control language myself.

I was building my personal website when the buttons started to feel wrong.

The first version was vibe-coded. The model had made some visual decisions by default. Transparency felt inconsistent with the rest of the interface, and other decisions had not been made at all. There were no real interaction states.

That did not make the button useless. It made the gap visible. I did not want the control language of my website decided by an agent or borrowed unchanged from someone else’s system. This is my website. Defining what a button is here is part of the design work.

A transparent outline with no point of view.

It lets the grid compete with the action. It does not establish material presence, and it does not explain what happens when someone touches it.

The experiment started inside a system that already knew the project.

By this point I had spent hours deciding what kind of website I wanted to build. The project already had a stack, visual tokens, a grid, a design brief, agent instructions, project notes, a live preview, and browser inspection tools.

The agent could help expand the option space quickly because the constraints already existed. My job was to inspect the output, notice what felt false, and decide what the system should become.

Twelve directions, shown compactly.

These are frozen artifacts, not production controls. The goal was breadth: enough contrast to see what the control language could become.

01

Solid slab

02

Signal rail

03

Split key

04

Offset plate

05

Inset key

06

Notched plate

07

Edge stripe

08

Double frame

09

Marker tab

10

Press key

11

Soft module

12

Control bar

A visible record of design decisions.

  1. Starting point

    Transparent, model-generated controls felt inconsistent. Their interaction states had not been designed.

  2. Exploration

    Expanded the space into twelve directions instead of accepting the first plausible answer.

  3. Selection

    Reduced the set to six directions worth deeper refinement: 01, 04, 05, 10, 11, and 12.

  4. Grid pass

    Calibrated controls to two vertical grid rows: 52px controls with 13px gaps.

  5. State pass

    Removed positional press movement. Press is communicated through surface, border, and shadow.

Refinement made the problem clearer.

I shortlisted six directions, aligned them to the same scale, and compared their interaction states. The more consistent they became, the less distinct they looked. I was refining one visual grammar, not six different ideas.

  • 01Solid slab
  • 04Offset plate
  • 05Inset key
  • 10Press key
  • 11Soft module
  • 12Control bar

The first divergence had a fundamental flaw.

The twelve-option pass looked broad because it contained twelve artifacts. Looking at them together, some felt amateur and most shared the same visual grammar: dark rectangles, decorative edges, and color without a clear job. I could have improved them by commenting on corners, shadows, and spacing one decision at a time. That would have produced better buttons, but it would not have produced a better agentic process.

I abandoned the branch instead. In a fresh session I kept the same website, harness, project context, and inspection tools, then changed the prompting strategy. Rather than ask for another matrix, I asked for one coherent interaction premise at a time and judged whether the idea deserved another pass.

Four ideas survived the reset.

The sequence moved from contact, to direction, to typography, to shape. Two additional proposals were tested and dismissed. They added complexity or texture without improving the control, so they are not shown here.

01

Contact becomes color

A print-registration response begins exactly where the control is pressed.

02

Direction becomes motion

The control previews forward movement before the action completes.

03

Type changes register

Typography and color define the state without changing the primitive.

04

The container steps back

The target stays fixed while its compact visual face changes fill and shape.

The process felt different because the work was different.

Instead of preparing a list of obvious corrections, I was curious to see what the next proposal would be. The model was not waiting for me to art-direct every pixel. It had enough room to form a position, while I still had a clear role in rejecting, redirecting, and selecting.

I also chose not to provide visual references. That was deliberate. I wanted to see what could come from the project context and the collaboration itself, rather than steering the agent toward somebody else’s answer.

This does not prove a universal claim about model capability. It shows something more useful for my own practice: when the first exploration failed, changing the structure of the work changed both the output and my relationship to it.

The exploration is moving again.

From here I can clean up one of the surviving ideas, create more options, or carry the same method into other components. The final shared control language is not selected yet.