← back
AI

I Vibe-Coded SwiperTab While Watching TV

Building SwiperTab (a browser extension) without manually writing a single line of code

Why coding by hand still matters

Before I share my vide-coding experience, I’d like to quickly talk about why coding by hand still matters.

I am a software engineer with 5+ years of professional experience and 7+ years of “fiddling” experience. I got out of college about 7 months ago. In other words, I am the perfect age to experience the ongoing shift in the way we approach programming.

I have always loved writing software. You can see that by taking a look at my GitHub page. I have 51 public repositories, ~40 private ones, and I also have around 80 projects sitting locally on my machine. COVID was a hyper-productive time for me.

The only thing I loved more than writing software was learning about the technologies powered by software. I will never forget the feeling I had a couple of years ago when I realized what “HTTP is built on top of TCP” actually means. Everyone knows that sentence. But what does it actually (intuitively) mean? I wanted to find out. I created a simple HTTP server and connected to it using a raw TCP socket.

At first, I sent random data. The HTTP server ignored me :( Nothing happened.

Then I sent bytes formatted like an HTTP/1.1 request.

GET /heok HTTP/1.1
Host: marindedic.com
User-Agent: CustomTCPClient/1.0
Accept: */*
Connection: close

What I received was the same kind of response I would have received if I had used the regular fetch route.

I’ve had many moments where I realized that something I’ve considered “complex” is actually much simpler in reality, and this was one of those moments.

HTTP/1.1 is not magic. It is an application-layer protocol where the client sends a formatted text request over a TCP connection, and the server parses that byte stream according to HTTP rules. People are scared of the word protocol so they just assume it’s too complex to dive into. A protocol is just a set of rules, and those rules can turn out to be pretty simple.

The reason I took this memory trip is because I still remember that moment as if it happened yesterday. I had a question, wrote a script, failed, tried again, got a eureka moment, and remembered it for life — because I did it with my own hands. I learned something.

If you do not code by hand at all anymore, you will not learn the topic in the same way. You may read about it, understand it temporarily, even memorize some of the stuff, but it will eventually become one of those things where you know that you knew it at one moment, but can’t remember it because it made no impact on you.

The same thing happens with high-school and college knowledge. You may ace the exam, but a few years later you barely remember the topic, because you stopped using that knowledge. That is perfectly OK and it happens to everyone. The important part is that we actually learned it. It changed our brain chemistry. We exercised our brain. We became smarter. These are life-lasting positive changes.

Look at the smartest people in the world. They were all heavy readers and learners at their young age, and now, at 50 years old, they still have the habit of learning and they are very good generalists, or even polymaths. These are the people that run companies and make moneeeey.

As Jordan Peterson would (hilariously) put it, READ MORE!

I went off-road a bit up there, but I wanted to express my concern for the future generations. As we go further into the future, we need smarter thinkers, mathematicians, physicists and scientists. I am not saying that the usage of AI is bad for that direction, but I see younger generations refusing to employ their mental faculties for even the simplest of problems

They ask an LLM, quickly scan the bolded parts of the response, copy the answer, and move on. Not great.

Why I wanted to vibe-code a whole project

I love using LLMs to boost my productivity. I’m even instructing other branches in my company on how to automate their common workflows using LLMs.

Vibe coding vs coding with agents

When talking about software engineering with AI, people often use the term “vibe coding.” But I think it is important to separate vibe coding from coding with agents.

Coding with agents means you still behave like an engineer. You define requirements, review the implementation, understand the architecture, test carefully, and remain responsible for the result.

Vibe coding is when you roughly know what you want, let the LLM make some decisions, and are not even obligated to look at the code. It allows you to watch TV shows while programming. As long as the vibe-coded product cannot harm the PC, expose confidential data, or become critical for anyone, I think vibe coding is fine.

For my own needs, I have vibe-coded two browser extensions, some shell scripts for my workflow, OS and monitor support scripts — I use i3wm, btw — and my personal website. I looked at the code because I was curious, but I did not really have to. The code was acceptable, the outcome was only for myself, and the projects were simple.

Take a look at this website. It is built using Astro. I DuckDuckGo-ed the best frameworks for static websites, found Astro, watched Fireship’s “Astro in 100 Seconds” video on Odysee, and then asked Claude to write a simple personal blog website using Astro with a neon/cyber theme, plus light and dark theme switchers.

After a 20-minute conversation, I had 95% of this website without any prior Astro knowledge. I’d say that’s pretty efficient.

Sadly, I cannot work that way on my job or on detail-important personal projects.

Take my main personal project as an example: Kiyeovo. It is a P2P messenger with dual network modes - you can read more about it on GitHub, full release is planned for June.

The initial inspiration for Kiyeovo was to create the most secure and private conversation experience possible. I’m not saying I achieved that. I’m just saying that was the idea. Because of that, there is no room for vibes.

Every line of code goes through two of my “human” reviews, and afterwards I also employ 2 agents to review it. Kiyeovo has been my main project for months now, so I did not have much vibe-coding experience.

My assumption was that most engineers had a similar opinion: Either use AI for specific features, thoroughly review the code, do not let AI make important decisions, OR only vibe-code extremely simple projects, like static websites or small personal tools.

A new perspective

However, recently I talked to a friend of mine and he showed me his workflow. Codex does everything for him.

These are not small projects. They are not huge either, but they are real projects. He lets Codex do its thing and checks the output every now and then. Not the code directly — mostly the output. When he sees something that he doesn’t like, he tells Codex to fix it. He probably does not even know which language the project is being built in (JK… I think).

That got me thinking… I have a notebook in which I write all of my ideas so I don’t forget them. I have 7 big project ideas that would take months, maybe even years, and around 20 small ones that could probably be done in less than two weeks. The smaller ones are not that beneficial. They are just interesting to me, so I will probably never prioritize them… Unless… AI can do it for me?

Actually, is that not the future? Me telling the computer what to do while sunbathing and receiving universal basic income because I cannot compete with our AI overlords?

Well, yes.

We are slowly stepping into the less-thinking phase of humanity, which we as humans love. Thinking is hard and costs energy. We evolved to conserve energy. Makes sense, right?

Trying it out

So, I set two goals:

  1. Create a browser extension that is like Tinder for tabs.
  2. Do not spend more than two hours on it.

You can find the project here.

It currently supports only Firefox. I also made it support Brave and Chromium, but I cannot register for a Google developer account because my country is not whitelisted. If someone from the whitelisted countries is willing to post the project for me, contact me :)

The experiment: Tinder for browser tabs

The idea was simple: I often have too many tabs open. Some are useful, some are not, and some are there because I have emotionally committed to reading them someday, even though I probably never will.

I wanted a browser extension that would help me clean tabs quickly and in a fun way.

One tab appears as a card. I decide whether to keep it or close it by swiping or pressing the appropriate keyboard button. Then the next one appears… Like Tinder, but for browser tabs.

And they shall call it… SwiperTab.

My workflow

I usually follow best practices when using coding agents. I set up custom prompts, define project rules, use MCP tools, skills, planning documents, and so on… but now, I just wanted to watch an episode of The Boys and make the LLM work for me.

I created a very short project vision document. It was around 20 lines of Markdown. Then I told Claude to come up with a plan and ask me any questions if it had doubts. I wanted to create a clear vision, but I did not want to micromanage the implementation.

Pro tip: Always tell agents that they must not have any assumptions or guesses before they start writing code. They are trained to allow you to work as little as possible, but if they wrongly assume some business requirement or a feature, the only one who pays is you. Don’t let it define the vision for you.

Claude had some reasonable questions:

  • Should the extension appear only when opening a new tab?
  • What should the default thresholds be?
  • How should the settings page behave?
  • What should happen when the cleanup is finished?
  • Should keyboard shortcuts be supported?

I was more than happy to answer those questions. After some back-and-forth, we came to an understanding regarding the vision.

Claude created the plan that followed the vision. It was a 5 phase implementation plan. I was tempted to read it and modify it, but Homelander was about to do some wacky stuff, so I just told Claude to implement the idea, not wanting to miss the wackiness.

After each phase was implemented, I employed another model to review the code.

That was basically the workflow:

  1. Claude implements a phase.
  2. Another model reviews it.
  3. Claude fixes the issues.
  4. Repeat.

I did that five times. The episode had not even finished yet, and I had a working prototype.

The first prototype

The prototype was rough, but technically - it worked. Great start. I went straight to testing.

The first thing I noticed was that the UX was… poor.

People love intuitive and smooth interactions, and LLMs still do not really have that feeling. They can create interfaces, but they do not always understand how an interaction should feel. For example, when I used keyboard shortcuts to close or keep a tab, there was no animation. The card would just disappear.

The cards were also too tall, and almost all of the content was placed in the top 25% of the card. It looked empty and unbalanced.

Then there was the completion behavior. The extension would auto-close five seconds after tab cleanup finished. That may sound fine, but it was not. The final page had useful information, and since the extension was embedded into a newly opened tab, it would close the tab without considering whether the user was still doing something.

There were at least ten UX issues like that.

After three prompts where I explained what felt wrong and how it should look and behave, the extension became much better.

The UX was alright, alright, alright.

Edge cases

The next thing I noticed was that Claude mostly covered the happy path.

It did not fully think about what would happen if:

  • tabs were opened simultaneously,
  • tabs were opened in quick succession,
  • multiple SwiperTab instances were open at the same time,
  • tabs were modified while cleanup mode was active,
  • the currently shown tab was closed outside of SwiperTab,
  • permissions behaved differently between browsers,
  • the user interrupted the flow in the middle of cleanup.

These are common-sense edge cases that most developers think about fairly quickly, but they were not covered in the initial implementation.

Maybe Claude wanted to keep the project small and light… or maybe a better instruction file would have helped… But no. Today is about vibes, and that would not be very vibey.

That’s why I fired up YouTube (The Boys finished by this point) and just kept on low-effort testing:

  1. Find a bug while watching a Valorant tournament
  2. Tell Claude
  3. Re-test

After around 3 hours, I stopped. Everything functioned well enough, and I was happy. I even told Claude to add Chromium support, and it did it in two minutes. I tested it on Brave, and it worked.

I knew I had broken the two-hour rule, but I did not care. The project was done while I was enjoying burek od mesa and some Valorant gameplay. I see this as an absolute win.

The code review

I promised myself that I would not write a single line of code, but I still wanted to check how Claude did.

I reviewed the codebase and quickly became disappointed.

At first glance, it looked fine. The structure and setup were acceptable. Functions were mostly atomic. Nothing was obviously catastrophic.

After a closer inspection, I saw things like:

  • 50 lines of code in a row without a single newline separating logical sections
  • React components that contained an entire page and workflow
  • repeated identical code in multiple places
  • no central files for shared logic
  • messy state handling,

I experienced an emotional escalation from dissatisfaction to what psychologists classify as anger.

No worries, though. I told Claude what was wrong, and it cleaned the codebase up in around five minutes.

Obviously, the problem was not that it could not have written better code. The problem was that it did not write better code until I explicitly demanded it because it optimized for “done”, and not for “done greatly”. But hey, that’s what implementation plans, system prompts and reviews are for.

Lessons learned

Usually, if I watch doomscrolling content or an episode of a show for even 20 minutes, I get annoyed and angry at myself.

After three hours of watching pure entertainment while vibe coding, that feeling was heavily suppressed.

I enjoyed not thinking for three hours, and afterward I did not feel the usual stress or guilt. The reason is pretty obvious: we are outcome-driven creatures.

If someone works 18 hours a day and ends up with a big house, a nice car, or a tank, we are impressed.

However, if someone works 18 hours a day and doesn’t have a tank, we do not pay much attention to them.

Both people may have put in the same amount of effort, but only one of them has an outcome.

That is the exact reason I did not feel bad after “wasting” three hours. By the end of it, I had a working app, I knew I could write a blog post about the experience, and most importantly, I thought it was cool.

Actually, now that I have written this whole thing out, I realize that I did not merely enjoy it. I loved it. I loved the concept of it.

Try it yourself

If you feel guilty about wasting time while watching something you enjoy, just dust off one of your million-dollar idea projects that you will never actually code, and start vibe coding it. You’ll thank me later.

I will definitely keep a vibe-coding session open on my second monitor whenever I am watching something longer than 20 minutes. It gives me a productivity illusion that keeps me from feeling guilty.

Thank you for taking the time to read this.

You can check out the result of this vibe-coding session here:

SwiperTab on Firefox Add-ons

I think it’s pretty dope.