DEV Community

Kazutora Hattori
Kazutora Hattori

Posted on

[Solo Development] Finding a place to study in Vancouver! Creating a map app with React and Supabase

Introduction

Hello!
For this assignment, we developed a self-study spot search app called "Study Spot Vancouver."
Using React, TypeScript, Supabase, Google Maps API, and Chakra UI,
we implemented a system that displays pins on a map, filters by criteria, and transitions to a details page.

This assignment allowed me to experience the entire process of API integration, state management, and UI design,
and it was a great opportunity to gain a deeper understanding of how a map app works.

Reason for Creating the App

  • Solving a Personal Challenge When searching for a place to study in Vancouver, Google Maps only offers broad categories like "cafes" and "libraries."

However, when it comes to actually studying, important information is available only on-site, such as quietness, availability of power outlets, and Wi-Fi.

In particular, there was very little information available about "places where you can study aloud," such as for reading aloud or practicing presentations, so I had to check locally each time.

To address this inconvenience, I decided to create a map app that allows users to search for study spots based on their criteria.

App Overview

GitHub Repository:
https://github.com/kazukashima/kadai5.git

This app displays study spots within Vancouver on a map, allowing users to easily filter their search by Wi-Fi, power, and voice access.

I also personally defined and implemented the following MVPs:

  • MVP1: Built a development environment using React, TypeScript, and Vite. Deployed to Firebase Hosting. Automated with make deploy.
  • MVP2: Built CI/CD with GitHub Actions. Executed automatic testing and deployment upon push.
  • MVP3: Incorporated the Google Maps API and displayed data retrieved from Supabase as pins on the map.
  • MVP4: Implemented a filter function that allows users to filter by Wi-Fi, power, and voice access.
  • MVP5: Clicking on a pin takes users to a detailed page displaying photos, addresses, and business hours. Add a link that opens in Google Maps.

Home Screen
Screenshot 2025-10-28 002647.png

By toggling the WiFi, Power, and Talking buttons in the upper left,
you can narrow your search by whether each spot offers WiFi, has a power outlet, and allows private conversation (out loud).
Screenshot 2025-10-28 002811.png
Clicking on a pin on the map
will display a pop-up with the facility name and basic information such as "WiFi, power, and voice-over availability."
Screenshot 2025-10-28 004907.png
Clicking the "View Details" button will take you to the spot's details page, where you can view information such as the address and photos.
Screenshot 2025-10-28 004919.png
Click the "Open" link on the details page to open the actual Google Maps page, search for routes, and view the surrounding area.
Screenshot 2025-10-28 004933.png

Technologies Used

Category Technologies Used / Contents
Frontend React + TypeScript + Vite
UI Library Chakra UI (toggle buttons, responsive design)
Database Supabase (cloud management of self-study spot information)
Map Drawing Displaying pins using the Google Maps API (@vis.gl/react-google-maps)
Deployment Firebase Hosting (automatic update to production environment)
CI/CD GitHub Actions (testing and automatic deployment on push)
Automation Makefile (simple execution with make deploy / make test)

Development Difficulties and Solutions

1. Google Maps API and React Re-rendering Issues

Even when React re-rendered, the Google Maps display did not update,
and pins did not change even when switching filters.

The cause was that React's Virtual DOM and Google Maps rendering were running on separate systems.
To solve this, we adopted a method of changing the key and re-rendering, such as <Map key={JSON.stringify(filters)}>.

<Map key={JSON.stringify(filters)} ... >
Enter fullscreen mode Exit fullscreen mode

2. Filter State Management (Handling Boolean Types)

When switching between three conditions (WiFi, power, and voice output),
we managed them all together using useState, allowing for dynamic updates.

const [filters, setFilters] = useState({
wifi: false,
power: false,
talking: false,
});
Enter fullscreen mode Exit fullscreen mode

By using toggleFilters to toggle specific keys each time a button is pressed,
multiple conditions can be easily switched.

3. Transition to Details Page and Google Maps Link Generation

Clicking a pin on the map transitions to a details page, where a "Open in Google Maps" link is dynamically generated.

<a
href={`https://www.google.com/maps?q=${spot.latitude},${spot.longitude}`}
target="_blank"
rel="noopener noreferrer"
>
Open in Google Maps
</a>
Enter fullscreen mode Exit fullscreen mode

We learned that by using template literals (...),
we can dynamically construct a URL from latitude and longitude.

Points of Growth/Lessons

1. I gained the ability to integrate with external APIs.

I was able to experience the process of integrating external services, such as the Google Maps API and Supabase, into my own app.
The biggest benefit was understanding API key management, asynchronous processing, and handling environment variables.

2. I learned to design with an awareness of data structure.

By considering the Supabase table design (id, name, latitude, longitude, wifi, power, talking) in conjunction with UI behavior, I gained the ability to be aware of the relationship between data and UI.

3. I understood the relationship between state and rendering.

Through the issue of pins not updating when switching filters, I learned that React re-rendering and external library (Google Maps) rendering operate separately.


Impressions/Conclusion

There are still challenges remaining, such as improving the UI/UX and adding data to Supabase.
However, through the experience of designing my own MVP and completing the app in stages, I feel I have acquired the ability to proceed with development with a purpose.

Going forward, I would like to further increase data, improve the UI/UX, and develop the app into one that can actually provide value.

Top comments (0)