What I built
Crawl Vote helps groups on the move pick a next spot. Whether they’re looking for poutine in Montreal or tacos in Tijuana, Crawl Vote will return some suggestions for everyone to vote on together.
Demo link
https://crawlvote.com
Link to code
Helps groups on the move choose a next spot
Crawl Vote
Helps groups on the move choose a next spot
Installation
git clone git://github.com/nholden/crawl_vote
cd crawl_vote
brew install redis postgresql heroku
bundle install
yarn
cp .env.example .env
bundle exec rake db:reset
Getting started
Sign up for a Pusher Channels app at https://pusher.com/signup and a Yelp API key at https://www.yelp.com/developers/documentation/v3 and update .env
.
Start these long-running processes in separate terminal windows:
heroku local
webpack-dev-server
Crawl Vote should be accessible at http://localhost:3345 (or whichever port you specify in .env
).
Testing
Contributing
Contributions are welcome from everyone! Feel free to make a pull request or use GitHub issues for help getting started, to report bugs, or to make feature requests.
License
This project was created by Nick Holden and is licensed under the terms of the MIT license.
How I built it
Crawl Vote uses Ruby on Rails on the back end Vue.js on the front end. I used Webpacker, which comes with a Vue integration, to compile and bundle my JavaScript, CSS, and images. I used Tailwind to quickly prototype my design without writing any CSS.
I used Pusher Channels in a couple ways. When a user first submits where they’re going and what they’re looking for, Crawl Vote creates a new “crawl”, gives it a unique name, and subscribes the user to a Pusher channel with that name. Then, the application kicks off a Sidekiq job to query Yelp’s Fusion API in the background. Once the job has fetched relevant businesses and persisted them to the PostgreSQL database, it triggers an event to the Pusher channel. When the user’s browser receives the event, a Vue component uses the Fetch API to make a request to grab all of the relevant data and display it on the screen.
Once the user has successfully created a crawl and invited some friends, Pusher Channels allow everyone to see the voting in real time without refreshing their browsers. When a user clicks the vote button next to a spot, it makes a request to the application that persists the vote and triggers an event to the Pusher channel. When all the users’ browsers receive the event, the Vue component makes another request to refresh the data on the screen.
I had never used Vue’s List Move Transitions before, but I was really impressed how, with very little CSS, Vue added silky smooth animations as spots moved up and down in the rankings. Magic! ✨
To identify users, Crawl Vote assigns each person a UUID and stores it in the user’s session. When a user first visits a crawl or refreshes the page, the applications identifies the user directly from the session and renders the data server side. When the user’s browser receives a Pusher event letting it know that it’s time to fetch more data, the UUID is sent along as a token in the authorization request header.
Crawl Vote is continuously deployed to Heroku by Travis CI and is served by Cloudflare. I’m using Rollbar for exception tracking and Papertrail for logging. The only thing I paid for was the domain name, which came from Namecheap.
What’s next
I’m happy with how things turned out for this MVP, but I have a whole bunch of things I’d love to try with more time. I’d like to increase test coverage, including at least one or two Rails system tests that click through my Vue components using Headless Chrome.
I’d also like to continue improving the UX/UI, including adding autocomplete to the form fields. The categories that Yelp’s autocomplete endpoint returns look like they could be useful for the “Find” field, and I’ve been happy working with Google’s Place Autocomplete in the past. The design overall could use a little sprucing up, and I think some thoughtful use of color could help the look and feel better reflect the spirit of the app.
Finally, it would be great to do some more tweaking with the parameters Crawl Vote sends along to Yelp’s API. There are a lot of options, and I’m not sure I’d want to expose too many to the user since the complexity could turn people away, but I’d love to do some optimizing to make sure Crawl Vote returns a great selection of spots for every query.