MS

Hello, I’m Michael Sliwinski, founder of Nozbe - to-do app for business owners and their teams. I write essays, books, work on projects and I podcast for you using #iPadOnly in #NoOffice as I believe that work is not a place you go to, it’s a thing you do.

How I vibe-coded a simple to-do list with free AI in a few hours…

✔️Productivity,🔗Shortcuts,⭐️Featured

Being busy with my business and just making it better, I’m kind of late to the whole AI game, but over this past year finally I’ve started testing different AI models and tools to help me get more things done, quicker. Also, internally we’ve been testing using AI inside of Nozbe to help our customers get things done smarter. Today, I want to share my early attempts at vibe coding, meaning how I built a simple to-do list in plain JavaScript for my family and how you can use it as well, before you decide to upgrade to a fully blown to-do list like Nozbe. Here’s the story:

How I vibe-coded a simple to-do list with free AI in a few hours…

Simple To-do list in JavaScript, with Shortcuts support

Before I tell the whole story, here’s the result:

🌎 Basic Empty To-Do List

The link above is simple to remember: michael.team/todo

If you don’t want an empty to-do list, you can check out pre-defined to-do lists like these:

…or if you want send your own list of things to do to my “app” and check them off there, you can use this simple Shortcut:

🔗 To-do list Shortcut

This Shortcut asks you for a list of things to do and then sends them over to my to-do app and then you can check things off.

Features of my to-do list at michael.team/todo

This to-do list is very simple but the key features are the ones I really cared about:

How I vibe-coded the to-do list? Here’s the entire process!

First off, I know that there are better tools for this job, but I started simply with a free Copilot app on my M4 iPad Pro - because as you know, iPad is my main computer.

My first prompt was something like this:

Write ma a simple to do list in JavaScript (JS)

I know, very short prompt. It gave me a simple JS code. So I asked for more:

Add to it an HTML form for adding tasks

Now I could add tasks. Great, I asked for more:

Add support for Local storage so that the tasks remain Saved in browser memory

It did just that. The code worked, the to-do list remained saved locally. But I wanted more:

Add a checkbox next to a to do item so when you do it, it is checked off

It worked. So:

Add support that not only when I click on a checkbox but also on the name of the task item it gets checked off

It fixed the code and now I could click on entire task to check it off. Then:

Add possibility to specify a predefined list of items in JSON format so that I can fill out a to-do list with them

Great! I got a JSON format that could be used. But I asked it to simplify:

Simplify the JSON so that it’s only a list of to-do items without completed state

It worked. Now:

Add a button to reset the to do list and clear the local storage and use the predefined items

It did it, but broke the checking things off code. It was its first mistake. I asked it to correct itself:

The checking off of tasks doesn’t work now

Fixed! AI fixed itself. Perfect. I asked for more:

Change the delete button so that it only shows a trash can emoji

Worked! Now I needed a better styling:

Can you style the to do list with css so that it looks nicer?

It added style and made it responsive, too! So I asked for more tweaks:

please add “are you sure” question to when I want to reset the list

Great, and then:

add a confirm message for task deletion

Amazing. I wrote none of JS or HTML or CSS code up until this point. And I had a working to-do list!

Vibe-coding part 2. When I took over!

Now I hit a road block. I asked it for more features. I wanted to have a support for several lists in JSON format and then ability to save them in local storage separately. Well, it started to make mistakes, so I took it from there. Meaning, I was asking it for only some pieces of code and then I was gluing them up by myself as I do know some JavaScript.

Turns out when the app becomes complicated, this simple AI model started spinning its wheels and making new mistakes each time, so I had to kind of take ownership of the app and ask it for some small pieces.

However, I could also ask it some generic JavaScript questions, instead of relying on documentation:

I asked more questions and it helped me a lot. But the best part came later:

Vibe-coding part 3. Compatibility with my old iPad!

I was so happy with my simple to-do app that I wanted to launch it on my iPad 3 in the kitchen and it didn’t work at all! I was puzzled, but thought it might be a problem, because the device is 13 years old, so I asked:

how to find out which version of Safari on the iPad?

It turned out, the iOS version is the Safari version, so my old retina iPad 3 is at version 9. So I asked:

which JS functions are not supported on Safari below version 10?

It explained everything to me. Then I thought that now I’d have to re-write my entire code to make it compatible with the old JS, right? No! I asked the AI to do just that:

(added text file) can you rewrite this Javascript code so it’s compatible with Safari version below 10?

This blew my mind. It altered the code but when I launched it on my old iPad it just worked! I was stunned. So I asked for one last thing:

can I make an if statement to detect safari and load JS compatible with safari below version 10 and the new one?

That’s it, I added the “if” statement and it works as advertised.

Want to check out the code? It’s open source!

I don’t know if you know, but my entire blog is completely open source and available on GitHub. Feel free to check it out!

Now, as to the code of this to-do app, here it is:

That’s it. That’s the code, feel free to review it or improve it by submitting a pull request.

Bonus - me talking in Polish about vibe coding…

If you speak Polish, I discuss this entire process on the podcast “Nadgryzieni episode 547”.

Thursday, September 4, 2025 /list/