I've been a backend web developer for several years now. Swimming in the waters of databases, object oriented programming, and beautiful frameworks like Laravel to create some fairly robust web software for the company I work for, DieselCore. But here I was, realizing that learning a new programming language was well overdue. Sure, I had worked with Javascript plugins and packages before, I considered myself to be capable enough to figure the implementation part out even if I didn't really understand the language itself.
I bit the bullet and signed up for Wes Bos' free 30 day javascript course, Javascript 30. From the day I write this post to when I signed up has been exactly 14 days, and I'm still only halfway through. That has roughly been the extent of my javascript training, in truth, with only a few other small introductions to the language in passing.
That's why I feel proud to have created what I did in such a short time frame. A working web application that scans barcodes, talks to the grocery chain's non-public API, adds products to a list, calculates the total and factors in sales tax.
First-world problems
Let me back up a few steps to a couple of days ago. My wife, Kaitlynn, and I are having dinner while our kids play and she drops a real first-world problem on me: "I hate going to HEB (our local grocery store) because I can never tell what our total will be until I'm at the checkout. By then I may decide something in my basket isn't worth it." I grin, "oh, that's terrible." She laughs and continues, "but if I use the app to order, I feel cheated because we end up focusing on the price and eating the same food over and over. I just miss out on the experience to see new foods that spark fresh meal ideas if I'm not there."
I'll admit, I have a personal love for web APIs, having built several, myself. I begin to think of solutions. "I'm sure there's an app for what you want", I say. I look it up, and there is, but it's limited to locations that are nowhere near ours. Even if it's a first-world problem, I like to problem-solve, and my wife is a fantastic homemaker. If I can make her work even a little bit easier with what I do, I'm hooked.
I check out the HEB app and sure enough: they have barcode scanning. I look up a barcode and try it run it through HEB's web site search - no dice, UPC codes don't return results. But I know there is an endpoint out there serving up product results for UPC codes. But how do I find out where it is?
A clever solution
I remember something my father-in-law always talked about: WiFi honeypots. With the right software you can view network traffic. So, I hatched a plan. I would monitor my home network traffic while using the app and try to catch the outgoing API call.
After awhile I finally settled on the simplest solution: an iOS app called Thor. I started the network sniffer, opened the app and scanned. I crossed my fingers and began scrolling through the network logs hoping I would strike gold.
Bingo! I had an endpoint, and more importantly, I had an api key. This was starting to look like a real possibility now.
I made a few test calls and it worked perfectly. I got to work building the interface. I opted to use the fantastic CSS framework, Tailwind, for my UI. I hooked up all the Javascript components using what I had learned in the prior 14 days and things started looking good.
I did encounter some issues while attempting to utilize Javascript's fetch
function, namely CORs errors. So, for the remote API calls I whipped up a quick PHP script to send cURL calls on behalf of my javascript application. That was the extent of PHP's involvement in this project!
Smile for the camera
Now all I had to do was find a way to use a device's camera to convert a barcode and pass it to the API. I had been avoiding this part of the project as much as possible because I knew the limitations of my knowledge well enough to know barcode scanning was more advanced than I could handle right now.
Luckily, there are some really solid JS frameworks out there that handle this very thing. After some digging I found Quagga JS. I had a little bit of trouble getting the configuration right, mainly because the examples they provided didn't 100% match the source code they used, but eventually I got it working.
Here's a fun fact for anyone who has never worked with a device's camera permissions with Javascript: You need an SSL certificate. The browser won't even request access if your script is running on an unprotected protocol. For me, fixing this problem was a cinch because I use Valet to run my local development server. valet secure <folder>
and done. I was running https protocol. It was just that easy.
In less than 2 full days I had a working beta version of the web app which promised to cure my wife's shopping woes. See for yourself. Click the image below to watch it in action.
Thanks for taking the time to share in my story. If you're a developer, I hope this inspires you to go out and make something great.
Technologies used
- Thor - iOS network sniffer app
- Tailwind CSS - css framework for ui development
- Font Awesome - icons
- Quagga JS - camera access and barcode scanning
- Valet - local web server w/ ssl support
- HEB - for their kind understanding that I borrowed their api 😅
By the way...
HEB, if you're reading this, I'm open for contract web development work, I'm great with APIs 😉
I love to share
I have several free open source packages available for download on my Github profile. Check them out and see if any of them can save you time in your next project!
Top comments (5)
Nice work, Mark! So has HEB shutdown your access to that private API yet? 😎️
Like you, I found QuaggaJS to be grossly out of date, but was able to get it working...almost. It open the camera, I can see the video, but it doesn't do anything with barcodes. From your demo video, it appears the detection and decoding is automatic--once the barcode is in the view, it just finds it and decodes it--firing Quagga's
onDetected()
handler. Right?My onDetected is never firing and no errors in console.
Thanks for sharing you work! ☕️
I love reading solutions like this. Makes me remember why I started. Great job!
Wow! This is so naughty :) Great work. Here is a list of barcode apis one can use in place of QuaggaJS.
Thanks for sharing this!
Nice - was thinking of making a little app like this and stumbled across this article. Is your source code for this available? Would be a great reference point if it was!