DEV Community

Leif
Leif

Posted on

"Vibe Grokking" My Way Into an Apple Watch App

Tl;dr:

I needed an Apple Watch app to check the temperature sensors in my RV while my dog was in there, which didn’t exist. The company that made the sensors (TempStick, https://tempstick.com) graciously opens up their APIs to developers, so you can build your own software as needed. The only problem? I don’t know SwiftUI and there’s no cross-platform JavaScript/Typescript library to build watch apps that I’m aware of - you HAVE to do it in Swift. I heavily relied on partial “vibe coding” to get a prototype down, and am pretty happy with the results, although uneasy about potential security problems I don’t know to catch due to lack of experience with building Swift apps, although this is balanced against the low-risk nature of the project itself.

If you would like to work with me, please reach out - I’m always looking for new opportunities, primarily in the JS/TS domain, but am happy to branch out. Pictures of the doggie doing what she loves to do, which is sleep on the travel trailer couch, for the algorithms. I am not paid by the TempStick company but it’s not for lack of trying; unfortunately their paid affiliate program is not accepting new applicants at this time but I’d love to pump their product and get a commission.

Link to public github repository with the Apple Watch and companion iOS code:
https://github.com/leifdroms/TempStickMonitor-public

Intro:

Whew! What a journey this has been, “vibe coding” my first Apple Watch App and companion iOS app.. Well - not entirely. I didn’t exclusively beat up an LLM with prompts until I had a fully functioning Apple Watch App loaded onto my Apple Watch, but I did manage to use Claude and ChatGPT to get things going and prompt as needed to fill gaps in my knowledge, and the end result is a fairly simple, but functional Apple Watch app that does exactly what I wanted it to do. And some more - which was unnecessary, but harmless (I will dive into that).

Background:

My wife and I love traveling in our travel trailer and are not afraid to admit it. It provides most of the comforts of home, and our extremely lazy, chunky dog “Luna” (pictured above, hiding under a blanket) is more than happy to curl up on the RV couch for a nap with either the air conditioner or the heat pump going if we are out and about without her (no, we don’t burn propane in the furnace with her alone in the trailer - it gets shut off when we’re away for safety).

Which brings up some issues of safety. For those who are unaware, most RV’s are just plywood boxes, maybe with some aluminum siding, with minimal insulation and a rubber roof. It doesn’t take long if the air conditioner or heater fails for the inside to either get dangerously hot or cold depending on the weather, either through an equipment fault or power loss where we are staying. As a measure for peace of mind, like many RV-ers with pets, we keep temperature sensors in the RV which monitor and report environmental conditions inside the vehicle back to the cloud, which we can then check with our phones, and are programmed to give SMS and app alerts if something is amiss so we can rush back and take care of it before the situation gets dangerous.

Because I tend to be a paranoid person, we were as until recently running 3 different temperature sensors in the trailer: two by one manufacturer, TempStick (https://tempstick.com), which I built the Apple Watch app for and will get into in a moment, and another by a competitor that shall remain unnamed. The problem with the competitor’s sensor is that the subscription was very expensive for what it does (report temperature and humidity to the cloud), compounded by the fact that it relies on an internal cell modem, whereas Tempstick monitors are Wi-Fi only. Now, that would normally be a feature, not a bug, but as mentioned before, the siding on our RV is aluminum, which functions as a makeshift Faraday cage blocking cell signals pretty well, and the competitor’s temperature monitor has no place to attach an external antenna. At this point, the “Wi-Fi” only monitors are actually more fail safe in our situation, since I have attached an external 4x4 MIMO cell antenna to the roof of the RV to circumvent the signal blocking effects of the external aluminum siding, plus our travel router not only connects to cell towers, but has the feature of allowing backup WAN sources (Wide Area Network; i.e. connections to the Internet) to function in the case of a failure of the primary WAN. Most of the time we stay at a campground or park with some rudimentary, weak, and overloaded free Wi-Fi, but offering more than enough bandwidth for sensor uploads to the cloud as a backup. If that’s not available, we also have our Starlink we can set up which would also offer more than enough bandwidth for these purposes. All in all, at this point, there is not as much value in a “standalone” device with its own internal cell modem given our current setup with multiple fail-safes to provide internet access to our devices. Except for one thing the competitor did great that unfortunately TempStick has not implemented yet: An Apple Watch App to check sensor information.

Normally, there is no issue because I’m usually near my iPhone and can check the monitors anytime, but while doing things like swimming or tubing (as we love to do in the hot hot Texas heat), my phone is usually stashed in a pool locker or back at the truck, and I like to check in on the RV every half an hour or hour just to be safe. Not to mention, the less I pull out my phone while hiking with my wife, the less annoyed she is by all the distractions it offers that inevitably suck me in, which an Apple Watch is not quite as overloaded with. In these situations it would be very beneficial to have an Apple Watch app so I could check in on the RV right on my wrist, but sadly TempStick hasn’t implemented one yet, and didn’t have immediate plans to implement one after contacting them.

I did have the sensors configured to send alerts in case things went awry, and in testing I did in fact receive these on my Apple Watch, but I would only do so if something was wrong. I didn’t want to only get notified if something was wrong, but also to have the power to check that everything was alright and functioning properly. Not to mention, I frequently pause alerts when the trailer is unoccupied and sitting on the storage lot, and while I try to remember to turn them back on, I am human and sometimes forget.

Which leads us to the interesting part of this blog post: “vibe coding” to get this project done.

Well, not purely vibe coding, I suppose. I did look over the first 2 weeks or so of Paul Hudson’s excellent and free course, Hacking with Swift UI (https://www.hackingwithswift.com/100/swiftui), so I would have SOME understanding of what the code was doing and the concepts that were unfamiliar to me coming from a JS/TS background. Additionally, while the definition of “vibe coding” is not solidified in popular culture yet, I’m going to define it somewhat strictly and as “completely divorcing yourself from the code, allowing the LLM to handle everything, only supplying the prompts, and stopping when the results match what you intend”. I did not strictly do this, and to the best of my knowledge I could not do this at this time, because there’s no LLM that’s hooked up to fully release an Apple Watch app that I’m aware of like there currently are to release Web apps and handle all of the supporting infrastructure. But, credit is due where credit is due, so I’ll call what I have been doing as “grokking with vibes”, because that’s how I perceive it: using the LLM’s to get started, iterate from there, intuitively make my way through the code based on heuristics, and when the thing fails to compile, asking it for its opinion on what to change.

While I did not document every detail of this journey, it’s been an interesting one and I’ve had some take homes from it, in no particular order of importance:

Vibe coding has been a great starting point when coming out of my “comfort zone” and doing something I haven’t done before in earnest- Swift development. Outside of tweaking some configuration files and installing libraries via CocoaPods in Xcode to make a React Native project work, I was nearly completely new to the idea of poking around in Xcode to build something, and certainly completely new to developing an Apple Watch app. Plugging in your requirements into ChatGPT or Claude and saying “now build me an Apple Watch App” is a great way to jump off, and probably saved me several months of churn as I developed into a real SwiftUI developer, which was great, because - at this time I don’t have a need to be a “real” SwiftUI developer. I need to fake it well enough to develop one Apple Watch app for personal reasons, and probably won’t need to develop another Apple Watch app again, or at least for a long while. And now I have my watch app, without having to take time to become an expert.

Vibe coding is great to get a sketch of an idea and build on it, but relying on it completely would lead me into complicated loops of prompting the AI that were completely unnecessary. I was able to understand when this was happening based on my previous coding experience in other languages and frameworks, stop what I was doing, analyze the code and realize, “oh, this is simple, I just need to pass in a dictionary rather than converting it to an array like the first iteration of the AI was attempting to do”, but if I had no clue what any of this meant because I had never programmed anything and was unfamiliar with the concepts, I’d likely be stuck in these frustrating loops for days before eventually giving up (or paying someone to fix it if the end result would potentially make me money).

When deciding to build something where I knew “just enough” to get it going, security was in the back of my mind. Frequently with “purely vibe coded” projects done by people with zero coding experience, major security problems are introduced, including but not limited to leaking sensitive credentials like API keys in cleartext in the final product, configuring databases with no security, and so on. The worst secret that could get leaked in this project would be my sensor API key, which could potentially allow a hacker to see what the temperature and humidity in my RV is, or change my configuration without my consent, deleting sensors, etc. Both of these situations would be “pretty darn annoying” but neither would potentially ruin my life and could be rectified by creating a new account with TempStick to get a new API key, or contacting customer service. Since my sensor lacks a GPS receiver, I’m not running the risk of some weirdo hacker tracking my movements. That being said, I did look at the code that Claude/ChatGPT spat out, and did my best to decide whether or not it “made sense” and was reasonably secure for what I was doing; the LLM’s had made the decision to store the API key in secure Apple keychain storage and their implementation of this looked ok to my eyes. Additionally, I did check to make sure that communication between the iPhone app and the Apple Watch app through Apple’s Watch Connectivity framework is secure and encrypted (https://support.apple.com/en-in/guide/security/secc7d85209d/web). I’d say the biggest glaring loopholes to security that I was able to spot were pretty obvious: after developing, it was important to erase any calls to “print()” that would output credentials to the debugger. If someone had absolutely no clue about programming they might not catch this and it could be a problem.
Frequently, the LLM would do something I was unfamiliar with, and it was useful to prompt it to ask “why” it was doing so. For example, when implementing an observer in the Notification center in order to “do something” when either the watch app or the phone app would communicate with each other, ChatGPT-5 came up with some code using “weak self”. I didn’t know what this was or why, and could ask it. Was it a hallucination? Possibly, but considering it’s trained on the wider internet (including countless StackOverflow answers), its explanation appears plausible and correct, and I didn’t see an issue with going with its suggestion (ChatGPT-5):

Different LLM’s had different strengths and weaknesses. I found Claude was great for getting the initial project structure out, but it lacks the ability to output everything as a .zip file and simply load it in; the best you’d get was a pdf of all your files. I could then plug that into ChatGPT and split things up, as well as ask for its opinion on the code Claude had spat out.
I’m fairly impressed with the UI the LLM’s generated on the first try. While a lot of it was unnecessary for the use case in that I only really needed the companion iOS app in order to input my TempStick API key and adjust the polling settings for each sensor, I decided to keep it for simplicity and aesthetics. It recreates a lot of the functionality that the official TempStick phone app already created; i.e. displaying sensor names along with online status, battery level, temperature and humidity, but…it looks good and I don’t feel the need to cut it out since the LLM’s generated it with little effort on my part.

A lot of the code that the LLM’s output is messy and repetitive - which is not a good practice. Ideally the shared code between the watch app and the phone companion app would appear in one place, rather than be duplicated for each target, but I didn’t want to spend time to clean things up and make it look nice. The goal was to get a watch app out as quickly as possible for personal reasons, with a minimum amount of time spent on it. “In real life” at a “real company”, this should not and would not fly - this is a common way for nasty bugs to come up in the future as different people work on different parts of the codebase but don’t update everything as needed, especially as it grows. If I get really bored I will probably refactor this for my own purposes, but for now I’m going to purposely leave things as is, if anything to demonstrate one of the pitfalls of “vibe coding” as things stand as of the time of this writing.
Some of the functionality seems redundant but I’m going to leave it as is; pressing “Save Settings” in the iPhone app settings also functions to “Sync to Apple Watch”.
I’m not sure I trust some of the functionality but it appears pretty benign and not worth my time to correct for now; for example it appears that enabling Global Polling and setting the interval doesn’t actually change the interval of the sensors to hit the API on the iPhone app and they can only be changed individually, although it does appear to affect things on the watch app. Again, if I get bored, I’ll probably just cut out Global Polling completely to prevent confusion and require individual sensor configuration.
The LLM’s are NOT great at crawling documentation you link to in order to generate a functioning app that connects with the backend provided, or at least weren’t at the time I was developing the app. Maybe if I had copied and pasted all of TempStick’s API documentation directly it would have come up with something better on the first go, but the AI’s solution to this was to find a wild repo on the internet that made use of TempStick’s API, crawl that, and make its decisions from there. Which, as you may guess, didn’t work at this time (although maybe it would have worked with a previous incarnation of the TempStick API that the repo was based on). I had to look in the documentation myself and fix the problems. I still feel that this saved me some time vs. doing everything from scratch, but again, I’m relying on my ability to program or at least grok through something new-ish to me, whereas I’d be at a dead halt if I had none of that in the back of my brain. Interestingly, I tried again today, asking it to “make a demo web app” using the URL of the TempStick API documentation, which it spat right out, but when pressed (ChatGPT-5):

-Certain critical parts of functionality, like having the Apple Watch app poll the API on its own (rather than relying on data sharing between the phone app and it) were strangely commented out at the beginning and marked as “optional”. If I wasn’t looking for this in the code, everything would “appear” to work fine at first since generally speaking, my phone and watch are on at the same time, and the phone usually has a connection to the internet. If it were stuffed inside a metal locker in a concrete building at a pool or boathouse, there’s a good chance it wouldn’t be able to connect to the cell towers though, my watch wouldn’t receive updates on its own, and thus the whole purpose of the project would be defeated since in its initial form the watch app wasn’t configured to poll the backend on its own.

Summary:

As many have said before, AI is a great tool for those that already have foundational programming concepts under their belt, both in order to properly articulate what they’re looking for in addition to spotting and dealing with potential problems as they come up. In my opinion if I hadn’t had the experience I already had, I would have never been able to bring this specific personal project to fruition. For a purely web app, I do think it is possible to purely “vibe code” something and in this narrow regard the hype is indeed real, but except for the simplest client-side only web app with no authentication, no database access, no API usage, etc., doing so runs a huge risk of security problems, or at a minimum vendor lock…unless someone was able to vibe code their way around the cloud as well to set up the necessary infrastructure, and trusted the results (although I remain extremely skeptical this is possible at this point in time). At the end of the day, it’s important to remain vigilant, skeptical of the AI output, and to not use it as a substitute for your own reasoning and decision making, as Open AI warns about itself, right in the chat prompt box:

Although at the time of writing, it appears we are starting to hit a point of diminishing returns with new LLM’s and a plateauing of progress, I do think AI will continue to be a great resource for developers to brainstorm and sketch out rough ideas as well as slap together some boilerplate, greatly speeding up the process of development. Especially in a situation like I found myself in, where I NEEDED to learn and adopt a technology I didn’t have much experience with, I did not want to take months to become an expert in this domain because I will probably not use it much outside of this one project (at least for now), but didn’t want to wait for the company to produce their own Apple Watch companion app which doesn’t appear to be happening soon. I remain optimistic that I’ll see a more polished, “official” app though, since now one exists in the wild: mine!

Those are my thoughts for now, feel free to comment, and if you’d like to download the code and run it yourself, I created a public repo containing just the Swift files and the assets:

https://github.com/leifdroms/TempStickMonitor-public

I’d like to thank in particular the TempStick customer service team as well as the company in general for graciously opening up their APIs to developers. They make a great product and I’d recommend it to RV-ers or anyone else that needs to do cloud based environment monitoring. Gavin in customer support, if you’re reading this, thank you in particular.

Top comments (0)