Finding food that matches you should be easy
This week, I aimed to solve the age-old question: Where should I eat?
Along the way, I learned three important tips about web development that I will carry with me to everything else I decide to make.
I’ll first talk about the app I made to give you some context, and then I’ll dive into the problems I was presented with and what I learned by fixing them.
Of course, solutions for this already exist. You can pull up a Google search and fire out a quick search for “sushi near me” or look up an article about “top restaurants in Manhattan.” However, both solutions answer the question by forcing you to make an even harder decision between many choices, some of which you may have never heard of before.
My site alleviates this by only giving you one decision at a time: whether you want to eat at this restaurant or not. If you don’t want to eat there, you shouldn’t need to think about it anymore. If you want to eat there, you should be immediately taken to directions on how to get there.
These choices are encoded into gestures. A swipe left means to ignore that restaurant and no longer consider it. A swipe right leads to the Google Maps page for that restaurant, where you can easily find directions. You only have to make one decision at a time, making the whole process as streamlined for someone as indecisive as me.
Responsive inputs can feel amazing. As soon as you start typing in an input field, autosuggestions can pop up, and other queries can start happening. However, some things just shouldn’t happen on every keystroke.
For my app, I initially had the text input set up so that every keystroke would fetch from the Yelp API, find and set locations and businesses, and change the location on the map. This caused the map to jostle around and load several towns based on partial inputs. Trying to search for “midtown Manhattan” would lead to a search for “m” and “mi” and “mid” and every other possible substring starting from the beginning.
My solution to this was a concept called debouncing. This makes it so that it is physically impossible for the function to be called several times within a certain time interval, effectively throttling the relationship between the input and its effects. Now the search only fires once the user has cooled off on typing in their input, giving the expected results.
In terms of implementation, I found this article very helpful with ways to do it with React primitives. Of course, someone has made a library for debouncing input fields called react-debounce-input, so I used that instead. Implementation is as easy as replacing inputs with
This may sound obvious, but you are the first person to use your site. And according to Jakob’s law, you have spent much more time on sites other than the one you just started developing yesterday. You’re a good judge of how sites work and your new site should behave. So, use it!
Even as you’re developing, be the user and interact with your site constantly. And if something is confusing to your user’s brain, put on your developer hat and fix it!
In the case of Where Should I Eat, I found this most evident in how I handled the URL. I used the barely-developed version of the site whenever I was out with friends, and I found myself confused whenever I tried to press the back button on my browser, and it completely navigated me away from the site. The internet has taught me that if I want to undo, I can navigate back and expect the change to be undone.
To fix this, I lifted my state into the URL. Now, whenever a major change was made to the location of the search or the food that the user was craving, this would be reflected as a URL parameter. So, if a user decided they weren’t feeling tacos and wanted to return to their previous sushi choice, they could naturally do that by navigating back to their browser.
Quick aside: If you’re using Next.js and its router to handle putting the state into the URL, I would recommend using shallow routing and setting the scroll option to false if you’re finding issues with state changes jerking your site’s scroll or data around.
Originally, I wanted to use the Google Maps API. I was quickly met with a credit card form and a pricing scheme that scares the part of me that hopes my app is an overnight success. And this doesn’t even include using their map tiling for generating the dynamic map. (They provide $200/month of free requests, but I learned that after I started my site.)
Instead, I reached for free alternatives. The Yelp Fusion API provides me with place information such as reviews, locations, and business hours with a solid 5,000 requests/day without upgrading to an enterprise plan. Additionally, the pigeon-maps package leverages free tiling solutions such as OpenStreetMap to provide dynamic and well-tooled maps for React.
Of course, I still wanted to use Google Maps at the end of the day. To still get that integration, I simply used the queried latitude, longitude, and place name from Yelp to construct a Google Maps URL that would take me right to the correct place. There is a helpful guide I found for doing that.
Now I can get similar functionality without breaking the bank and with no noticeable hits to the user experience. I’ve comprised on not using the Google Maps API but have lost no major features to my app!
I hope to level up my development so the only issue I have is coming up with the next unicorn startup idea! And I hope to share some of the wisdom I learn along the way with all my readers!
Thanks for reading!