At the start of 2024, on the heels of deciding to move across the country, I determined that I needed to ensure that I spent as much time in the company of the people I cared about as I could before leaving. What better way to do this than to set up a recurring weekly event at my apartment. So a natural first step was to develop a website.
Hosting movie nights was the natural choice given my tiny living room could cram 10 people who like each other if we shifted the couches around and drug out the bean bag chair. I had a 65" OLED TV mounted on the wall with 3 channel audio and a Plex server (with Jellyfin running as backup when Plex would occasionally go on the fritz) serving 4K HDR Blue-ray rips. All it was missing was the subwoofer, because I was trying to be a courteous neighbor.
The Problem
This naturally presented two engineering challenges:
- How do I keep track of who is coming?
- How do we decide what to watch each week?
Tackling the first, I immediately ruled out sending a mass text. I hate notification spam, and in my experience as an introvert with introverted friends, once a group chat expands beyond 4 members, there will always be someone who wants to leave but won't say so because it would be awkward. Individually texting people and manually tracking RSVP statuses sounded like a headache. And just imagine the never ending series of texts asking, "Who else is coming?" There are of course ready made solutions to this conundrum. A Discord server could solve this problem trivially, send a weekly announcement and use reactions for RSVPs. But, not everybody has a Discord account, and not everybody necessarily wants their discord profile picture shared with their coworkers (looking at you anime waifu havers). Facebook events exist too, but I don't have a single friend my age who wants to open the Facebook app ever again. Besides, neither of these would address the second problem.
The second problem could be rephrased as, "I don't want to pick the movie. How do I make someone else do it?" As host I didn't want to hold the audience captive to my eclectic tastes, Annihilation and Swiss Army Man are not everyone's cup of tea, and I wouldn't want to show an unvetted new film, risking a bad experience all round. The solution is collective responsibility. If everyone has a voice in what we watch, then even if the movie sucked, at least we would be in it together.
The Solution
I decided to hack together a website and send the link to everyone I wanted to invite. There they could RSVP, see who was coming, suggest movies, and vote on suggestions. I put everyone on the invite list's name and phone number in a json file so people could just enter their phone number and it would identify them. This approach acted as a whitelist, and identification method without needing a full log in. Of course, this is rife with security concerns. Anyone could log in with anyone else's phone number. It fails completely to securely fulfill any of the 3 forms of authentication:
- Something you know
- Something you have
- Something you are
However, this wasn't a public app with anything at stake. I was hosting a http server on an old, pared down, gaming PC in my bedroom and sending the link to less than 20 people who I trusted were not going to try and hack the system. Self-hosting toy software is fun, you should try it.1



The website interfaced with The Movie DB to provide fuzzy movie title searching and retrieve movie metadata like poster images. They are an incredible community built IMDB-like database of every movie you can think of with a developer-friendly API.
In the first iteration, voting was allowed all week via an upvote button on each movie. This worked well enough for the first few weeks, but I noticed a pattern. There was a bias towards the movies suggested first. People were more likely to vote immediately on RSVPing and not change their votes at the end of the week. So they were less likely to vote for a movie suggested after they RSVPed. I wanted it to be more fair and also to be more fun. I asked for feedback and my party requested a downvote button and later the ability to see how many up and down votes each had, rather than the single quantity of up minus down votes. Apparently being negative is fun, despite what YouTube says. So I made two changes, the downvote button, and also making it so voting was only available on the last day. Now there was fierce competition. On the last week, voting closed at 7:00PM, and there was a dramatic upset with Pirates of the Caribbean: Curse of the Black Pearl showing after Eternal Sunshine of the Spotless Mind was downvoted to oblivion at 6:59 when someone said "I heard it's depressing." Is it depressing? Who can say, because I still haven't seen it.
How It was Made
And so, I undertook my first vibe coding project, back before the term was coined. After a few false starts where poor prompting led ChatGPT to design complex architectures with 3rd party cloud-based dependencies, I prompt engineered the following. You can read the full conversation here, though some of ChatGPT's responses seem to be missing.
Help me develop a web app for scheduling movie nights with my friends designed to be used from our phone browsers. My use cases:
- RSVPing. I have a static list of friends who may attend, and I want them to be able to identify themselves on the app by entering their phone number and allow them to mark whether they will attend or not. Ideally they only have to log in once from their phone browser using a cookie for persistence.
- Movie recommendations. Once they have RSVPed, I want attendees to be able to recommend 1 movie for the week's movie night. There should be a movie search box which is hooked up to some 3rd party API to auto complete or fuzzy search movie titles and provide thumbnails of the movie poster
- Attendees can +1 someone else's movie recommendation, which means attendees should be able to see other attendees and their recommendations.
I can host a node server and want to write the UI in React with Typescript. I want to keep this project to the bare minimum code necessary, so I want to host everything as one server rather than having a front end and back end architecture. I have a pre-defined list of phone numbers and their owner's names, I want to keep these in a simple json file so I can update it manually. I also want to avoid integrating with a database since my data will be super simple, so just reading and writing to a file in a directory will suffice.
The first thing I want you to do is lay out an outline of how we will develop the project, starting with the project set up, followed by each step to develop the project. Each step in the outline should be designed so that after it's been implemented, I can run it and verify that it works or troubleshoot with you as needed until we're ready to implement the next step in the outline. Once you've written the outline, I will make any comments I see fit.
Second, I will ask you to repeat the outline but this time with a detailed explanation of what we are doing and why, for example during the project setup phase you should identify all the node dependencies that will need to be installed. If during this detailed explanation, you identify any steps in the outline that would cause a conflict or issue, I want you to stop and explain the issue, I will then prompt you to restart the outline.
Once we are satisfied with the detailed project plan, I will ask you to give me the code and/or commands to execute for each step in the outline, I will run it or copy it to my project files, verify that it works or troubleshoot with you, then you will give me the next chunk of code. Lets begin with the outline
It took 2 evenings of work, copy pasting back and forth, before it was ready to deploy. There were many lessons to be learned from this experience of building a complete app solely with an LLM. The start of the conversation, explaining requirements and aligning ChatGPT to what I wanted to build, required my full faculties as a developer. My experience, critical thinking, and vision of what I actually wanted to build were able to prune the complexity of the app way down from what ChatGPT initially spit out and reduce the impact of hallucinations accumulating errors. Starting in the form of an outline, collaboratively creating a design document and incrementally moving it towards implementation details, meant that I could read and understand the logic of the proposed application much quicker than asking for code immediately. This approach minimized the most painful aspect of developing (with AI or otherwise), finding yourself in a dead end where the code or configuration you've spent hours on is now an obstruction to an unforeseen requirement.
But once the outline was hammered out, all I had to do was copy and paste between VS Code, the terminal, and ChatGPT and the app all came together. It became a rather braindead, albiet enjoyable, activity from then on. Re-reading the conversation, I can't help but laugh at the level of non-thinking necessary to have written this prompt after working with Typescript for 2 years of full time employment.
How do I undeclare a variable in node? const filePath = path.join(process.cwd(), 'data',
week-2.json
); Uncaught SyntaxError: Identifier 'filePath' has already been declared".
Even if my Typescript experience was all in front end and not Node, I think this prompt more than anything demonstrated to me that having AI write all my code is a surefire way to inhibit my critical thinking. If something else is carrying the cognitive load, then the mind will gladly skip over the hard work of processing what's in front of it. I felt this especially after people began using the app and I encountered bugs and found room for improvement. Adding features to a code base that I essentially did not write took much longer than if I had internalized the architecture fully through puzzling through the process myself. However, with a small app like this one, it didn't take too long to become familiar with it to add features such as a downvote button for movie suggestions.