Flatiron School Phase 1 project: "Atmos Weather"

How I built a frontend web app using JavaScript, HTML, and CSS

Flatiron School Phase 1 project: "Atmos Weather"

I just finished Phase 1 of the software engineering course at Flatiron School!

For the Phase 1 project, we were tasked with building a single-page frontend app using JavaScript, HTML, and CSS. I chose to build a weather app because I was eager to work with real-world data.

Users can add/remove locations to see current temperature, current time, current weather condition, as well as a table with the forecast for the next 6 hours. Users can also toggle between Fahrenheit and Celsius, and as a nod to my past career in localization, I implemented a simple i18n function and localized the app into pt-BR!

I also illustrated all the weather icons using Procreate — a fun side-project that allowed me to tap into my creative side.

The project took about 5 days to build, which is incredible given that I just started learning this stuff a month ago!

Below are more details about the project:

Requirements

The project required us to build a single-page frontend app using JavaScript, HTML, and CSS, with access to data from a public API or from a local database using json-server, and had to use at least 3 types of events. Another requirement was to manipulate data with array methods such as forEach(), filter() or map().

The MVP

As a first step, I took sometime to figure out all the functionality I wanted my app to have, and wrote them out as a list of user stories.

Writing user stories was not required, but it helped me a) ensure that my project met all the requirements and b) organize the work and stay on track given the limited time, essentially working on mini sprints each day, with 2 or 3 stories, depending on their size.

With this "MVP" (Minimum Viable Product) planned out, I did some discovery to select the APIs and get familiarized with the data available — this informed me of how the user stories could be implemented.

APIs

I chose the Open-Meteo API because it’s well-maintained, easy to use with URL parameters, and doesn’t require an API key.

The Open-Meteo API takes a location in the form of latitude and longitude parameters. Initially, I created a form for these inputs, but later iterated it with an address search input field connected to the Google Geocoding API. This way, users can input an address, which the Google API translates into the respective latitude and longitude.

The location’s name, lat and lng are then posted to a local db.json file using json-server. When the page loads, the app fetches the locations from the database and creates a card forEach location.

The app also fetches the user’s settings (that is, temperature unit and locale) from the local db.

I also chose to use a third public API called WorldTimeAPI to display the current time, because the Open-Meteo API only returns the “current” time in 15 minute intervals.

Here is a flowchart reviewing how all the API calls interact to create the app:

Flowchart: how all the API calls interact.

Manipulating the data

The greatest challenge I faced in this project was related to the table with the weather forecast for the next 6 hours. I wanted this table to be dynamic (meaning it starts at the current time).

However, the hourly data array from the Open-Meteo API always begins at 00:00 for the current date, so first I had to calculate the current time, and then slice the hourly data accordingly.

Here's a snippet of the code

// Slice the current time from the weather API call, search for it in the array of hourly data, and get its index:
const indexOfFirstHourly = locationWeatherData.hourly.time.indexOf(`${locationWeatherData.current.time.slice(0, 14)}` + `00`);

// Since we want to display the forecast for the next 6 hours in the table, we calculate the 6th item in the array of hourly data counting from the first:
const indexOfSixthHourly = indexOfFirstHourly + 6;

// Initialize a nextSixHours array and then iterate on the hourly weather data to get the data for the 6 hours:
const nextSixHours = [];

for (let i = indexOfFirstHourly; i < indexOfSixthHourly; i++) {

    const hourlyObj = {
        time: locationWeatherData.hourly.time[i],
        temperature: locationWeatherData.hourly.temperature_2m[i],
        temperature_unit: locationWeatherData.hourly_units.temperature_2m,
        is_day: locationWeatherData.hourly.is_day[i],
        cloud_cover: locationWeatherData.hourly.cloud_cover[i],
        rain: locationWeatherData.hourly.rain[i],
        snowfall: locationWeatherData.hourly.snowfall[i]
    };
    nextSixHours.push(hourlyObj);
 }

// Execute the function to create the hourly forecast table, with the nextSixhours and location as arguments:
createHourlyForecastTable(nextSixHours, location);
})

CSS Flexbox

The CSS for the app was also tricky, particularly getting the user preference toggles to display at the top corner on the right side.

Playing with the position, flow and hierarchy or elements proved quite challenging. I ended up using Flexbox as a solution to determine how to position the elements correctly.

Next steps

There are a few use cases that I didn't implement, and could be included in a future iteration of the project.

For example, the location search is limited to the first element of the array with search results, so a search for "Paris" will return "Paris, France". If the user wanted to add "Paris, Texas, USA", they would need to provide a more detailed input.

A possible iteration would be to display the array of search results and let the user pick.

Another example is the localization of location names. The search bar sends locale to the Google API, so the search results are localized. However, once the name is stored in the local database, it won't be localized again if the user changes their language setting. This could be solved with a more robust i18n solution.

Phase 2 and beyond!

For Phase 2, we will be learning to use React to build front-end applications. I'm excited for all that is to come!