Building an SPA with the National Parks API
By this summer, I’d grown accustomed to the total drag of the coronavirus lockdown in California. If there was a silver lining, though, it was having extra time on my hands. Extra time? I questioned. Extra time, my brain explained patiently, can be used to acquire new knowledge and make things. Eureka! I began searching for APIs to work with and came across one offered by the US National Parks Service. I figured if I couldn’t visit any national parks in person, I could do so in spirit.
I restricted the scope of the project to the state of California to keep the amount of data manageable. Even then, it seemed to take a while to get the data from the API. This led me to research ways of caching the park data so that users wouldn’t have to re-download it on every visit. I settled on the localStorage web API for this task. That introduced a wrinkle when I decided to include park alerts. I didn’t want users to have stale data for important park announcements, after all. My solution was to set different cache expirations for park data (which shouldn’t change often) and park alerts (which could change within the day).
My next prototyping action was to get all the park coordinates and display them on a map using the Google Maps API. Once I had that, I could figure out what to do when a pin was clicked – which would share the same UX when clicking a park from a list – and then I’d be off to the races.
That’s when I really dug into the possibilities of displaying the data using Vue. I was surprised how natural it felt to use this framework. In pretty short order I had a list of park “cards”, which, on click, would populate an information panel that slid into view. For this size of a project, Vue made it relatively easy to control what appeared, and when.
Since the user has already downloaded data for all the California parks, I also added a “Random Park” button, as well as a simple search function to filter the list of cards.
The next technical hurdle had to do with asset management. Since this was a fairly small stand-alone project, I took the opportunity to learn about Webpack to bundle everything. Having used Gulp in the past, it wasn’t conceptually foreign to me, but was different enough to have a learning curve. I was able to use Webpack to process my Sass into prefixed and minimized CSS, and transpile my JS files (allowing me to take advantage of ES6 features), outputting an optimized package to serve to users.
At this point, I was pretty happy with the project. The app was by no means a trip planner, but I felt it could be a just little more useful. I took some time to think about what I usually do when planning a trip. The app could already handle basic info like park location, information about closures or fees, open hours, typical conditions. When I imagined using the app, I realized the most helpful thing would be an actual weather forecast. Not in any great detail, just: is it expected to rain? Is it going to be hot?
I knew what I needed: a weather API that could provide a forecast based on the park coordinates that I already had. The OpenWeather API was a perfect fit. It even included icons for different weather conditions! Here, too, I made sure the weather data had a reasonable cache expiration, and only requested the weather data when a park was clicked.
Time for the final touches. Knowing new visitors would have to wait to download the data, I included an introductory loading screen that could also show an error message if there were any issues. I also committed to a slightly retro look and feel. I wanted the app to be evocative of history, hard-working rangers, colors you might find in the landscape, and even family road trips where my dad let me thumb through the road atlas.
Lastly, while I had been using git this entire time to manage my work, I hesitated to push any of it to github because I didn’t want to expose any API keys. My last piece of research solved the issue via .env variables. I was finally free to share the project with the world, if a bit late in the process.
Even though I intentionally kept the scope of the project small, I couldn’t be happier with how it brought me through a wide variety of web dev fundamentals: from integrating multiple apis and using a js framework, to organizing and displaying data as well as optimizing the user experience. I learned a ton to apply to future projects. I can even imagine updating and extending this project some day. But for now, I have a simple and informative tool for those weekend trips out of the Bay Area.