I first wrote about generative AI in this blog in 2023. Since then, Copilot Agent mode has been introduce in Visual Studio Code and things have come a long way! I was able to create a fully-functional MVP in 3 hours using Agent mode with GPT 4.1 in Visual Studio Code - this would have taken me weeks or months to complete without tools like this.
Frugality Drives Innovation π
I had just finished my first outdoor ride after putting my $20/mo subscription to the cycling training program Zwift on pause for the summer. The heat and wildfire smoke inhalitaion had me thinking I wouldn’t be able to meet my mileage goals outdoors, but I didn’t want to keep spending $20 - despite Zwifts many features, I only use the robo-pacers 99% of the time. Robo-pacers offer a constant output workout which I can mindlessly do for hours and build bike endurance.
Zwift offers some key features which are very valuable to me:
- recording output from my smart trainer
- having a virtual pacer to guide my output
- a minimally interesting scenery
- outputting the workout to Strava
After spending a lot of time writing code with generative AI, I thought a simple cycling sim with these features could be achievable with vibe coding. I highly underestimated how quickly it would come together.
Prompting is THE new Skill π
Web-based gaming, 3d animation, device-browser interfaces, and client-side optimization are all strategies or technologies which I have modest experience with. I’m not an expert in any of them, but I understand the capabilities which exist and have an idea of how to implement them. I think this level of knowledge is the sweet spot for vibe coding.
Getting the initial prompt right is very important for setting the context for the agent, so I asked Windows Copilot to help me create a prompt for the coding agent:
help me craft a single prompt to work with claude on a new programming project. I have the high level idea, but need to specify all the details for claude to code it out in one go. Here is the idea. I want a cycling simulator similar to zwift or rouvy which runs in the browser. For connecting to the cycling trainer input, we can use Bluetooth and wahoo’s api docs. For displaying the rider, 3d terrain, and hud we can use a-frame javascript library. I don’t need a fancy world, just one other pacer rider - I can set their constant watts - and we can place groupings of built-in 3d elements to create a basic 3d environment
The following is what Windows Copilot produced and what I used to start with Visual Studio Code Copilot Agent mode:
Prompt: π
Create a prototype for a browser-based cycling simulator inspired by Zwift or Rouvy. The app should run entirely in the browser and use JavaScript-based technologies. Below are detailed specifications to guide development:
π§ Core Features π
- Bluetooth Connectivity:
- Use Wahooβs API documentation to connect to a smart cycling trainer.
- Poll real-time rider data such as power output (watts), cadence, and speed.
- 3D Environment & Visualization:
- Use the A-Frame JavaScript library to render the 3D world.
- Include terrain elements and ambient scenery using built-in 3D primitives.
- Visualize the rider as a simple 3D avatar that moves based on power and cadence.
- Add a fixed βpacerβ rider with a constant power output (e.g., 200 watts).
- HUD (Heads-Up Display):
- Overlay showing:
- Current power
- Cadence
- Speed
- Distance traveled
- Time elapsed
- Position relative to the pacer
- Strava Integration:
- After each ride, export session data to Strava using the Strava API.
- Include metrics like distance, duration, average power, and optionally a GPX or TCX file.
- Authenticate users via OAuth and use the createActivity endpoint to upload ride data.
- Mark activities as indoor trainer rides (trainer=1) and optionally add a description.
βοΈ Design Considerations π
- Keep the UI clean and minimal.
- Prioritize performance and compatibility with modern browsers.
- Modular codebase with clear separation between Bluetooth handling, A-Frame rendering, and Strava export logic.
π§ͺ Stretch Goals π
- Save session data locally or to a cloud database.
- Allow terrain selection or route customization.
- Add support for other Bluetooth fitness devices.
- Please generate a modular codebase structure, identify key components, and draft initial HTML/JavaScript boilerplate to demonstrate basic functionality, including Bluetooth device connection, A-Frame scene setup, HUD overlay, and Strava export logic.
From this prompt Copilot created five javascript files, an html file, and a project README in a new folder. The files were organized intuitively, having a main.js
and other feature-specific files, like bluetooth.js
and scene.js
. The code itself was boilerplate, and this helped me work through the implementation iteratively with Copilot.
3D Development π
The rider models were just cylinders, so the first thing I asked was to update them to be more rider-like. Without my knowledge of A-frame, the edits Copilot made would have been impossible to correct. For example, Copilot added wheels along the x plane while the bike frame was along the z plane; this happened a lot when updating the rider model.
Knowing that rendering a scene of basic elements instead of bringing in assets would be better for client-side apps, I asked Copilot to build a basic scenery of trees and buildings using native a-frame elements. It did a pretty good job - giving me rectangular, grey rectangular prizms for buildings and green spheres atop brown cylinders for trees.
Animations π
Copilot then helped me test the movement of the rider. We iterated through a keyboard-based testing system that would allow us to build this without connecting to the cycling trainer. With that, we went from moving the rider through the scene to moving the scene toward the rider and moving the pacer relative to the rider - this is where game-development knowledge came in!
Sometimes I find that bringing two features together can be really tricky for Copilot. I wanted to again make some 3D scene enhancements after we had worked on animation. This resulted in prizms being placed overtop the rider for the first 10 meters. This occluding prizm issue was very difficult for Copilot to overcome, and I had to debug and fix the code manually. The source of the issue was scenery code which had been written in animation handlers.
Export to Strava π
Being able to export and track past workouts is one of the most valuable parts of Zwift for me. I understood that Strava has an API and a file-upload method of adding activities. The API would be preferable, but the file-upload would be sufficient.
After Copilot told me I would need an API Key, I transitioned to the file-upload method. This was easy enough to test with the keyboard, and it worked immediately! I then transitioned to testing with the trainer and had to make some updates to the bluetooth code before I could test how cycling power would be exported to Strava.
Connecting the Trainer π
This is where my experience saved the most time. There were so many hiccups that could have been major time sinks without my knowledge guiding Copilot to avoid them. For example, when Firefox wouldn’t launch the bluetooth window, I immediately switched to Chrome and I could search for devices. No devices were showing up, though.
Copilot had written some cycling trainer specific filtering on the bluetooth devices, so I knew removing that would be the best way to debug. We stripped away everything until we were logging bluetooth notifications from any device we connected to. Eventually we saw power logs in the console and I told Copilot to build the rest of our functionality off that.
After this, the only thing left was to update the export functionality to include point-in-time power data. Below is the activity we created from the sim and the final product of 3 hours of collaborating with copilot!
Looks Around in Programmer π
Uhh, so weeks or months of work can now be completed in a few hours. What does that mean for programmers? It’s simultaneously very exciting and very scary. I think there are a lot of opportunities, but we need to change the way we approach learning software engineering.
Coding is no longer king. This is what we learn as we progress to more senior levels of contribution in software engineering, but junior engineers will face this reality now, too. It will be a very difficult transition for those who are just entering software engineering with an education and hiring process that was focused on writing lines of code to accomplish tasks.
To make the transition, we must focus on layers of abstraction above and below the programming language. Not only do we need to understand the impacts the generative AI coding agent is making on our infrastructure - including performance and security - but we also need to understand how we can use the agent to develop valuable code.
I’ve spent hundreds or thousands of hours learning about the intricacies of coding languages; this is now mostly irrelevant. The most valuable parts of my learning have been in exploring feature capabilities and the biggest opportunities I have are deep dives on infrastructure fundamentals.
Further reading π
Here is a video demo of the sim working and a live example will be hosted at https://gioandjake.com/zlow (make sure to use Chrome).