Skip to content

Commit 5aefa97

Browse files
committed
Merge branch 'main' of github.com:codedex-io/projects
2 parents 3212a4e + 3e89fab commit 5aefa97

File tree

2 files changed

+334
-72
lines changed

2 files changed

+334
-72
lines changed

projects/build-a-cafe-finder-with-javascript/build-a-cafe-finder-with-javascript.mdx

Lines changed: 61 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ uid: CgUQBagDrWWBRUuoh3mkyi3aedg1
55
datePublished: 2025-08-06
66
description: Learn how to build a cafe finder with JavaScript
77
header: https://i.imgur.com/VKm4oPJ.gif
8-
bannerImage: https://i.imgur.com/VKm4oPJ.gif
8+
bannerImage: https://i.imgur.com/lfbCFid.gif
99
published: live
1010
tags:
1111
- intermediate
1212
- javascript
1313
---
1414

1515
<BannerImage
16-
link="https://i.imgur.com/VKm4oPJ.gif"
16+
link="https://i.imgur.com/lfbCFid.gif"
1717
description=""
1818
uid={false}
1919
cl="for-sidebar"
@@ -29,38 +29,37 @@ tags:
2929
/>
3030

3131
<BannerImage
32-
link="https://i.imgur.com/VKm4oPJ.gif"
32+
link="https://i.imgur.com/lfbCFid.gif"
3333
description=""
3434
uid="CgUQBagDrWWBRUuoh3mkyi3aedg1"
3535
/>
3636

37-
**Prerequisites: HTML, CSS, JavaScript**
38-
37+
**Prerequisites:** HTML, CSS, JavaScript
3938
**Read Time:** 30 minutes
4039

4140
## Introduction
4241

43-
If you're an iced-bev-meets-coworking-space fiend like me and want to shake up what cafe you head to next, this is the perfect project for you. We'll be using our trilogy of web dev tools: ****HTML****, ****CSS****, and ****JavaScript****, and an API from the Google Maps Platform called ****Places****. We'll also make some quick animations and implement swiping recognition with a JavaScript library called ****Hammer****!
42+
If you're an iced-bev-meets-coworking-space fiend like me and want to shake up what cafe you head to next, this is the perfect project for you. We'll be using our trilogy of web dev tools: HTML, CSS, and JavaScript, and an API from the Google Maps Platform called [Places](https://developers.google.com/maps/documentation/places/web-service/overview). We'll also make some quick animations and implement swiping recognition with a JavaScript library called [Hammer](https://hammerjs.github.io)!
4443

4544
## About the Google Maps Platform
4645

47-
The Google Maps Platform is a collection of Application Programming Interfaces (APIs) and Software Development Kits (SDKs). Each tool on the platform lets users use Google Maps functions and data in their own projects!
46+
The [Google Maps Platform](https://mapsplatform.google.com) is a collection of Application Programming Interfaces (APIs) and Software Development Kits (SDKs). Each tool on the platform lets users use Google Maps functions and data in their own projects!
4847

4948
Some popular apps that use the Google Maps Platform include Uber and Airbnb, which access a user's location to calculate rides and show rentals in specific areas!
5049

5150
<ImageZoom src="https://miro.medium.com/v2/resize:fit:7680/1*ThzU2nLvoAHfPwLqlddwhQ.png" />
5251

53-
The [Places API](https://developers.google.com/maps/documentation/places/web-service/overview) is a smaller API under the Google Maps API. It fetches location data like location names, addresses, photos, and many more attributes! It's a great tool for accessing updated data and finding multiple places without manually copying all of their information into a project. ****We'll be using this in our project!****
52+
The [Places API](https://developers.google.com/maps/documentation/places/web-service/overview) is a smaller API under the Google Maps API. It fetches location data like location names, addresses, photos, and many more attributes! It's a great tool for accessing updated data and finding multiple places without manually copying all of their information into a project. We'll be using this in our project!
5453

5554
## Setup
5655

5756
### Workspace
5857

59-
Start by creating a new HTML/CSS/JS project in [Codédex Builds](https://www.codedex.io/builds). You can also use a Code editor of your choice, like [VSCode](https://code.visualstudio.com/).
58+
Start by creating a new HTML/CSS/JS project in [Codédex Builds](https://www.codedex.io/builds). You can also use a code editor of your choice, like [VS Code](https://code.visualstudio.com/).
6059

6160
### Google Cloud Console
6261

63-
Set up your project in the [[Google Cloud Console](https://developers.google.com/maps/documentation/elevation/cloud-setup). You'll enter a project name and billing information. Your website won't work as it should unless you enable billing, but you won't be charged if the API doesn't get called past the monthly limit (we'll teach you how to cap it at the limit, which is usually 10,000 API calls).
62+
Set up your project in the [Google Cloud Console](https://developers.google.com/maps/documentation/elevation/cloud-setup). You'll enter a project name and billing information. Your website won't work as it should unless you enable billing, but you won't be charged if the API doesn't get called past the monthly limit (we'll teach you how to cap it at the limit, which is usually 10,000 API calls).
6463

6564
### Clone Template
6665

@@ -87,67 +86,62 @@ Here's how to create and protect your API key:
8786
3. Make sure you're on your cafe finder project and select the APIs & Services button.
8887
4. On the left menu, click on library.
8988
5. Search for the Places API (new) and click on it. Make sure the Places API is enabled.
90-
6. Click on the hamburger menu and look for the APIs & Services button again. Then click on ****create** **credentials ****, then API key.
89+
6. Click on the hamburger menu and look for the APIs & Services button again. Then click on **create credentials**, then API key.
9190
7. After your key is generated, click on edit key. Restrict your application to websites.
92-
8. Add the domain your project is hosted on. In my case, mine is hosted on Codédex builds.
91+
8. Add the domain your project is hosted on. In my case, mine is hosted on Codédex Builds.
9392

9493
Put your API key at the top of your JavaScript file. It should look like this:
9594

9695
```jsx
9796
const apiKey = "STRING_OF_RANDOM_CHARACTERS_HERE";
9897
```
9998

100-
<aside>
101-
⚠️
102-
103-
****Make sure your API key is restricted to just your project (step 7), or else anyone can use it freely and you'll get charged for it!****
104-
105-
</aside>
99+
**⚠️ Warning:** Make sure your API key is restricted to just your project (step 7), or else anyone can use it freely and you'll get charged for it!
106100

107101
### cors-anywhere
108102

109-
Head to [https://cors-anywhere.herokuapp.com/](https://cors-anywhere.herokuapp.com/). Make sure to click on the ``Request temporary access to the demo server`` button to get set up with a temporary server for your project.
103+
Head to [https://cors-anywhere.herokuapp.com](https://cors-anywhere.herokuapp.com/). Make sure to click on the ``Request temporary access to the demo server`` button to get set up with a temporary server for your project.
110104

111105
Then, add these lines to the top of your JavaScript file.
112106

113107
```jsx
114108
const useProxy = true;
115-
const proxy = "https://cors-anywhere.herokuapp.com/";
109+
const proxy = "https://cors-anywhere.herokuapp.com";
116110
```
117111

118112
### Geolocation
119113

120114
To see cafes nearby, the browser needs access to your location. There's a built-in JavaScript function that takes care of that for you called ``useLocation()`` and it takes your device's latitude and longitude coordinates.
121115

122116
```jsx
123-
function getLocation() {
124-
const cache = JSON.parse(localStorage.getItem('cachedLocation') || '{}');
125-
const now = Date.now();
117+
function getLocation() {
118+
const cache = JSON.parse(localStorage.getItem('cachedLocation') || '{}');
119+
const now = Date.now();
126120
```
127121
128122
Next, we'll check if any location data has been cached (saved to the browser) and is less than 10 minutes old.
129123
130124
```jsx
131125
if (cache.timestamp && now - cache.timestamp < 10 * 60 * 1000) {
132-
useLocation(cache.lat, cache.lng);
133-
}
126+
useLocation(cache.lat, cache.lng);
127+
}
134128
```
135129
136130
If there's no cached location information found, the browser pulls your current latitude and longitude from a built-in function.
137131
138132
```jsx
139133
else {
140-
navigator.geolocation.getCurrentPosition(pos => {
141-
const lat = pos.coords.latitude;
142-
const lng = pos.coords.longitude;
134+
navigator.geolocation.getCurrentPosition(pos => {
135+
const lat = pos.coords.latitude;
136+
const lng = pos.coords.longitude;
143137
```
144138
145-
We'll save the location and timestamp in ``localStorage`` in case we use our cafe finder website in the near future. Then we'll add error handling - an alert that lets you know if your location can't be accessed.
139+
We'll save the location and timestamp in `localStorage` in case we use our cafe finder website in the near future. Then we'll add error handling - an alert that lets you know if your location can't be accessed.
146140
147141
```jsx
148-
localStorage.setItem('cachedLocation', JSON.stringify({ lat, lng, timestamp: now }));
149-
useLocation(lat, lng);
150-
}, () => alert("Location access denied or unavailable."));
142+
localStorage.setItem('cachedLocation', JSON.stringify({ lat, lng, timestamp: now }));
143+
useLocation(lat, lng);
144+
}, () => alert("Location access denied or unavailable."));
151145
```
152146
153147
### Using the API
@@ -166,8 +160,8 @@ We'll call the API to find nearby cafes and *_fetch_* their urls.
166160
167161
```jsx
168162
try {
169-
const response = await fetch(url);
170-
const data = await response.json();
163+
const response = await fetch(url);
164+
const data = await response.json();
171165
```
172166
173167
If the API finds results for nearby cafes, we'll take that data and insert it into cards (we'll write the `displayCards` function next!)
@@ -193,26 +187,26 @@ We'll start by creating a container that takes the first saved cafe in our cafe
193187
194188
```jsx
195189
function displayCards(cafes) {
196-
const container = document.querySelector('.cards');
197-
container.innerHTML = '';
190+
const container = document.querySelector('.cards');
191+
container.innerHTML = '';
198192
```
199193
200194
We'll then make a for loop that iterates through the cafe list to…
201195
202196
- Create a new div to wrap each cafe card
203-
- Add a class (``swipe-wrapper``) to each card to keep card styles consistent
204-
- Adjust the card's ****z-index**** (display order) so that new cards appear under old ones
197+
- Add a class (`swipe-wrapper`) to each card to keep card styles consistent
198+
- Adjust the card's **z-index** (display order) so that new cards appear under old ones
205199
206200
```jsx
207-
cafes.forEach((cafe, i) => {
208-
const wrapper = document.createElement('div');
209-
wrapper.className = 'swipe-wrapper';
210-
wrapper.style.zIndex = 200 - i;
211-
212-
var newCards = document.querySelectorAll('.location-card:not(.removed)');
213-
var allCards = document.querySelectorAll('.location-card');
214-
});
215-
}
201+
cafes.forEach((cafe, i) => {
202+
const wrapper = document.createElement('div');
203+
wrapper.className = 'swipe-wrapper';
204+
wrapper.style.zIndex = 200 - i;
205+
206+
var newCards = document.querySelectorAll('.location-card:not(.removed)');
207+
var allCards = document.querySelectorAll('.location-card');
208+
});
209+
}
216210
```
217211
218212
We'll add more inside the function that inserts location information into each card by calling the Places API. Add a line that creates a card div and another line that assigns the card's class name to be ``location-card``.
@@ -239,7 +233,7 @@ const cafeData = {
239233
};
240234
```
241235
242-
Putting in tags between the ````` symbol when changing an element's ``innerHTML`` allows you to render HTML elements when functions run. We'll append (connect) the card to its wrapper, and append its wrapper to its container.
236+
Putting in tags between the ``` ``` symbol when changing an element's `innerHTML` allows you to render HTML elements when functions run. We'll append (connect) the card to its wrapper, and append its wrapper to its container.
243237
244238
```jsx
245239
card.innerHTML = `
@@ -257,12 +251,7 @@ container.appendChild(wrapper);
257251
258252
[Hammer](http://hammerjs.github.io/) is a library used to recognize touch gestures in the browser!
259253
260-
<aside>
261-
💡
262-
263-
A **library** is a collection of reusable resources like functions, classes, and pieces of pre-written code. An **API** is an interface that lets your code communicate with another application.
264-
265-
</aside>
254+
💡 A **library** is a collection of reusable resources like functions, classes, and pieces of pre-written code. An **API** is an interface that lets your code communicate with another application.
266255
267256
To make sure we have swiping gestures detected on the site, we're gonna import the library by adding this line in the ``<head>`` of your HTML file:
268257
@@ -274,17 +263,17 @@ We're going to add a function that detects left and right swipes and makes each
274263
275264
```jsx
276265
const hammertime = new Hammer(wrapper);
277-
hammertime.on('swipeleft', () => {
278-
wrapper.style.transform = 'translateX(-150%) rotate(-15deg)';
279-
wrapper.style.opacity = 0;
280-
setTimeout(() => wrapper.remove(), 100);
281-
});
282-
hammertime.on('swiperight', () => {
283-
saveCafe(JSON.stringify(cafeData));
284-
wrapper.style.transform = 'translateX(150%) rotate(15deg)';
285-
wrapper.style.opacity = 0;
286-
setTimeout(() => wrapper.remove(), 100);
287-
});
266+
hammertime.on('swipeleft', () => {
267+
wrapper.style.transform = 'translateX(-150%) rotate(-15deg)';
268+
wrapper.style.opacity = 0;
269+
setTimeout(() => wrapper.remove(), 100);
270+
});
271+
hammertime.on('swiperight', () => {
272+
saveCafe(JSON.stringify(cafeData));
273+
wrapper.style.transform = 'translateX(150%) rotate(15deg)';
274+
wrapper.style.opacity = 0;
275+
setTimeout(() => wrapper.remove(), 100);
276+
});
288277
```
289278
290279
### Saving Cafes
@@ -314,7 +303,7 @@ if (!saved.find(c => c.place_id === cafe.place_id)) {
314303
We'll need a fallback in case the cafe is already saved. Write an `else` statement that alerts the user if a cafe has already been saved, so it doesn't get duplicated into the saved list of cafes.
315304
316305
```jsx
317-
else {
306+
else {
318307
alert(`${cafe.name} is already saved.`);
319308
}
320309
}
@@ -328,8 +317,8 @@ Start by writing a function called `showSaved()`. Similar to the `displayCards()
328317
329318
```jsx
330319
function showSaved() {
331-
const container = document.querySelector('.cards');
332-
container.innerHTML = '';
320+
const container = document.querySelector('.cards');
321+
container.innerHTML = '';
333322
```
334323
335324
Then, add this line to parse through the list of saved cafes and save the information in a variable.
@@ -342,9 +331,9 @@ If the saved array is empty, it'll update the page by adding a ``<p>`` tag to sa
342331
343332
```jsx
344333
if (saved.length === 0) {
345-
container.innerHTML = '<p>No saved cafes yet 😢</p>';
346-
return;
347-
}
334+
container.innerHTML = '<p>No saved cafes yet 😢</p>';
335+
return;
336+
}
348337
```
349338
350339
For each cafe in the saved array, we'll make a card div, add the `location-card` class name, and update the card's content with `innerHTML` to include the current cafe's information.
@@ -383,7 +372,7 @@ If you're looking for another challenge or a way to spice up your project, you c
383372
384373
### Troubleshooting
385374
386-
- Make sure you're granted temporary access on https://cors-anywhere.herokuapp.com/.
375+
- Make sure you're granted temporary access on https://cors-anywhere.herokuapp.com.
387376
- Make sure to allow location access when you try out the site.
388377
389378
### Additional Resources

0 commit comments

Comments
 (0)