{"id":23511504,"url":"https://github.com/imaginary-cloud/react-weather-app","last_synced_at":"2026-01-24T00:10:44.638Z","repository":{"id":56252837,"uuid":"313302700","full_name":"imaginary-cloud/react-weather-app","owner":"imaginary-cloud","description":null,"archived":false,"fork":false,"pushed_at":"2021-10-18T21:46:15.000Z","size":307,"stargazers_count":2,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"workshop","last_synced_at":"2024-12-25T12:14:57.051Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imaginary-cloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-16T12:57:16.000Z","updated_at":"2022-03-03T07:11:23.000Z","dependencies_parsed_at":"2022-08-15T15:31:05.429Z","dependency_job_id":null,"html_url":"https://github.com/imaginary-cloud/react-weather-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imaginary-cloud%2Freact-weather-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imaginary-cloud%2Freact-weather-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imaginary-cloud%2Freact-weather-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imaginary-cloud%2Freact-weather-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imaginary-cloud","download_url":"https://codeload.github.com/imaginary-cloud/react-weather-app/tar.gz/refs/heads/workshop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239194182,"owners_count":19597988,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-25T12:14:59.407Z","updated_at":"2025-10-31T12:30:23.343Z","avatar_url":"https://github.com/imaginary-cloud.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Table of contents\n\n* [Setup](#setup) - General instructions to install Node 16;\n* [Bootstrapping](#bootstrapping) - Instructions to get the application running;\n* [A few goodies](#a-few-goodies) - Brief list of useful packages;\n* [Building a Weather app](#building-a-weather-app) - Detailed description of the desired functionallities;\n* [Next steps](#next-steps) - Suggestions of further challenges to enhance our Weather app.\n\n# Setup\nMake sure you have Node v15 installed and ready to go, either download it directly from its [download page](https://nodejs.org/en/download/current/), or through [`nvm`](https://github.com/nvm-sh/nvm), which we recommend for both Linux and macOS.\n\nFollow the next set of instructions to complete your setup with `nvm`.\n\n## NVM\n### Install Node v16:\n```bash\nnvm install 16.6.2\n```\n\n### Select Node v16\n```bash\nnvm use 16.6.2\n```\n\n### Validate that Node v16 is installed and available\n```bash\nnode --version\n\u003e v16.6.2\n```\n### Install npx\n```bash\nnpm install -g npx\n```\n\n# Bootstrapping\n## Create a React application\n[`create-react-app`](https://reactjs.org/docs/create-a-new-react-app.html) is a Node package curated by Facebook, that can be used to create a new React project, with the required support scripts and dependencies.\n\nThrough `npx` we able to download and execute the package in a single action to create a new react project:\n\n```bash\nnpx create-react-app@4.0.3 weather-app\n```\nNote: On the first time npx will ask you to install the ***create-react-app*** package. Just click ***y*** and it will install and create your first react app.\n\nAnd we have just created a new React project, that is almost ready to run.\nPlease take a few minutes browsing the generated files inside weather-app folder, mainly:\n* `package.json` - npm relies on this file for all of its iteration, from dependencies to available scripts;\n* `./src/App.js` - The main component of the generated application;\n* `./src/index.js` - Root of our web application, where `App` is mounted;\n* `README.me` - Description of the generated project.\n\n## Launching the application\n\n### Lunching our react application\n\nWe can now run the application on development mode.\n```bash\nnpm start\n```\nThe web application should be now running and accessible on a browser through [http://localhost:3000](http://localhost:3000).\n\nThe page will reload if you make any changes and will show any errors in the browser's console.\n\n\n# A few goodies\nBefore we start hacking away our weather application, we will take advantage of a few packages that will speed up our development.\n\n## Install **Material UI**\n[**Material UI**](https://mui.com/) is a well known and very popular library of polished UI components that can easily be reused.\nAll components follow an underlying theme, keeping our application with a consistent look and feel.\n\n```bash\nnpm install @mui/material@5.0.2 @emotion/react@11.4.1 @emotion/styled@11.3.0\n```\n\nUsage example:\n```JSX\nimport * as React from 'react';\nimport { styled } from '@mui/material/styles';\nimport Button from '@mui/material/Button';\nimport Card from '@mui/material/Card';\nimport CardActions from '@mui/material/CardActions';\nimport CardContent from '@mui/material/CardContent';\nimport Typography from '@mui/material/Typography';\n\nconst Title = styled(Typography)(() =\u003e `\n  fontSize: 18;\n  color: black;\n`)\n\nconst Footer = styled('p')(() =\u003e `\n  fontSize: 8;\n  color: grey;\n`)\n\nexport function SimpleCard() {\n  return (\n    \u003cCard\u003e\n      \u003cCardContent\u003e\n        \u003cTitle variant=\"h1\"\u003e\n          Title\n        \u003c/Title\u003e\n        \u003cTypography variant=\"h5\" component=\"h2\" gutterBottom\u003e\n          Subtitle\n        \u003c/Typography\u003e\n        \u003cTypography color=\"textSecondary\"\u003e\n          Main content of the card\n        \u003c/Typography\u003e\n        \u003cFooter variant=\"body2\" component=\"p\"\u003e\n          A footer note\n        \u003c/Footer\u003e\n      \u003c/CardContent\u003e\n      \u003cCardActions\u003e\n        \u003cButton size=\"small\"\u003eCall to action\u003c/Button\u003e\n      \u003c/CardActions\u003e\n    \u003c/Card\u003e\n  );\n};\n\n```\n\n**Material UI** brings along dozens of components that cover a fairly amount of scenarios and the following root components will be quite useful during our development:\n\n* [styled](https://mui.com/system/styled/) - Utility function to style existing components, like Typography, or dom elements, like paragraphs;\n* [Autocomplete](https://mui.com/components/autocomplete/) - Input with suggestions;\n* [Card](https://mui.com/components/cards/) - **Material UI**'s root Card component;\n* [Grid](https://mui.com/components/grid/) - Easy manage a 12 columns layout;\n* [Typography](https://mui.com/components/typography/) - Component for all kind of text, with a huge set of variants to fit titles, paragraphs, etc;\n\n\n## Install **date-fns** to handle dates\n[**date-fns**](https://date-fns.org/) is a popular package to handle and format dates.\n```bash\nnpm install date-fns@2.25.0\n```\n\nUsage example\n```JavaScript\nimport { format, parseISO } from 'date-fns'\n\nconst date = new Date(); // \"Mon Nov 18 2021 21:20:02 GMT+0000 (Western European Standard Time)\"\n\nformat(date, 'EEE d MMMM, h:mm:ss a') // \"Mon 18 October, 9:20:02 PM\"\nformat(parseISO(\"2021-11-18\"), 'MMMM do yyyy') // \"November 18th 2021\"\n```\n\nMore details about the available _formats_ can be found on  [**date-fns**'s docs](https://date-fns.org/v2.25.0/docs/format).\n\n\n# Building a Weather app\nOur weather app will consist of an [SPA](https://en.wikipedia.org/wiki/Single-page_application) that will display the current forecast details and the next few days' forecast, for a selected location.\n\nUsers should be allowed to search for a location. This search will guide our users, displaying possible locations containing the users' query as he types.\n\nUpon selecting a location, he should be able to check the forecast for the next 5 days and the details of today's weather report.\n\nWe will rely on [MetaWeather](https://www.metaweather.com/api/)'s data. It provides endpoints to search for a location from a provided query string and another to fetch the weather report of a location, through its [WOEID](https://en.wikipedia.org/wiki/WOEID) - _Where on Earth ID_.\nWe have sampled the response for a possible search and location's forecast to simplify our development.\n\nIn the `sample` folder, the next examples are available:\n\n* [`search.json`](./src/samples/search.json) - Available locations for the search query `li`;\n* [`weatherReports.json`](./src/samples/weatherReports.json) - Weather reports for the locations available in `search.json`.\n\nThey can be imported and used in the application:\n```JavaScript\nimport searchSample from \"./sample/search.json\";\n```\n\nThe next sections we will further detail the behavior and role of each element of our interface and supply tips in how to proceed.\nThese tips are only tips and nothing more, feel free to explore Material-UI's components to shape the interface to suit your taste.\n\n\n## Setting up a layout\nBefore jumping into more concrete blocks of our application we have to setup a general layout, it will work as the foundations of the interface and split it into sections where we will place the other elements.\n\n[Grid](https://mui.com/components/grid/) from Material-UI is quite handy to achieve such behavior. It creates a wrapper container with 12 columns, allowing a quick establishment of sections with a fixed set of columns for a specified resolution. Grid will adjust its sub-components to fit the current resolution following the provided props.\n\n\n## Searching for a location\nThis element consist of an input to type a location.\n\nIt will guide our user, displaying suggestions of locations that suit the provide input.\n\n[**Material UI**'s Autocomplete](https://mui.com/components/autocomplete/) component suits this task. It is capable of providing suggestions from a existing source and filtering them to match the input. Also provides a mechanism to establish the behavior for click actions.\n\n## Displaying the forecast for the next few days\nUpon selecting a location trough the search, this section should render a set o elements to display the forecast for the next 5 days.\n\nThis should display a summary, with the following information:\n\n  * Day of the forecast;\n  * Weather forecast, sunny, rainy, etc;\n  * Max temperature;\n  * Min temperature;\n\nThe forecast for the next 5 days can be found in the sample file, `weatherReports.json`, in the attribute `consolidated_weather`.\n\n[Card](https://mui.com/components/cards/) component are simple and effective ways of displaying this kind of information.\n\n## Displaying detailed view for today's forecast\nThis section should display the details of today's forecast, with all the information available, from current temperature to degree of humidity.\n\n\n# Next steps\n## Fetch data directly from the API\nUntil now, our forecast comes only from the sample files, but ideally, we should be fetching the data directly from [MetaWeather](https://www.metaweather.com/), but this is where it gets complicated.\n\nMetaWeather API doesn't have [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) enabled, so our browser will refuse to fetch data from it. As a work around, we can use [`local-cors-proxy`](https://github.com/garmeeh/local-cors-proxy#readme) to proxy the request and trick our browser.\n```bash\nnpx local-cors-proxy --origin http://localhost:3000 --proxyUrl https://www.metaweather.com\n```\n\nIn order to perform request to MetaWeather, [axios](https://github.com/axios/axios#axios) is definitely the right tool for the job.\n\n[react-query](https://github.com/tannerlinsley/react-query#visit-react-querytanstackcom-for-docs-guides-api-and-more) streamlines the usage of axios, so that it works as any other hook.\n\n```bash\nnpm install axios@0.23.0 react-query@3.27.0\n```\n\nSimple example, performing a request to MetaWeather to fetch a locations data through its _woeid_:\n\n```JavaScript\nimport axios from 'axios';\nimport { QueryClient, QueryClientProvider, useQuery } from 'react-query';\n\nconst queryClient = new QueryClient();\n\nfunction ForecastLocationDetails({ woeid }) {\n  const {\n    data,\n    isLoading,\n    isError,\n    error\n  } = useQuery(\n    ['getLocationForecastDetails', woeid],\n    () =\u003e  {\n      return axios.get(`http://localhost:8010/proxy/api/location/${woeid}/`)\n      .then(({ data } = {}) =\u003e data)\n    });\n\n  if(isError) {\n    return \u003ch3\u003e{error.message}\u003c/h3\u003e\n  }\n\n  if(isLoading) {\n    return \u003ch1\u003eLoading...\u003c/h1\u003e;\n  }\n\n  return (\n    \u003c\u003e\n      \u003ch1\u003e{data.title}\u003c/h1\u003e\n      \u003ch3\u003e{data.location_type}\u003c/h3\u003e\n      \u003ch2\u003e{data.consolidated_weather[0].weather_state_name}\u003c/h2\u003e\n      \u003ch2\u003e{`${data.consolidated_weather[0].the_temp}º`}\u003c/h2\u003e\n    \u003c/\u003e\n  );\n}\n\n\nexport default function App() {\n  const woeid = \"638242\" // Berlin\n\n  return (\n    \u003cQueryClientProvider client={queryClient}\u003e\n      \u003cForecastLocationDetails woeid={woeid}/\u003e\n    \u003c/QueryClientProvider\u003e\n  )\n}\n```\n\n## Setting up a map\nA map would be a great addition to our weather app. Since MetaWeather provides the latitude and longitude of a location, it would be nice to focus that location on a map.\n\nIt would be a bit awkward to make plans for a nice weekend BBQ based on the forecast for [Lisbon, Florida](https://en.wikipedia.org/wiki/Lisbon,_Florida) or some other [Lisbon](https://en.wikipedia.org/wiki/Lisbon_(disambiguation)#United_States), just in the USA.\n\nAs you can imagine, there are quite a few components at our disposal, and we suggest the usage of [react-mapbox-gl](https://github.com/alex3165/react-mapbox-gl).\nIt is quite simple to integrate and to display a point at a certain latitude and longitude.\nFeel free to play with their [demos](https://alex3165.github.io/react-mapbox-gl/demos) to get a feeling about how it works and look around their [documentation](https://alex3165.github.io/react-mapbox-gl/documentation).\nThe most important components to focus upon a location would be `ReactMapboxGl`, `Layer` and `Feature`.\n\nWe can install it into our project with:\n```bash\nnpm install react-mapbox-gl mapbox-gl\n```\n\n\nIn order to use react-mapbox-gl, we will need an accessToken, that we already requested:\n\n```\npk.eyJ1IjoicHNpbHZhaWMiLCJhIjoiY2tobmI5YTRlMDAzbTMxcGV6NDk3ZHNrdCJ9.mpgz1tj9j8cLrhrsZ5hlhw\n```\n\nThe snippet bellow we displays how we can create a Map, with the provide accessToken, that will focus upon Lisbon, Portugal and place a small marker:\n\n```JavaScript\n\nimport ReactMapboxGl, { Layer, Feature } from 'react-mapbox-gl';\nimport 'mapbox-gl/dist/mapbox-gl.css';\n\nconst Map = ReactMapboxGl({\n  accessToken:\n    'pk.eyJ1IjoicHNpbHZhaWMiLCJhIjoiY2tobmI5YTRlMDAzbTMxcGV6NDk3ZHNrdCJ9.mpgz1tj9j8cLrhrsZ5hlhw'\n});\n\nfunction MyMap() {\n  return (\n    \u003cMap\n      style=\"mapbox://styles/mapbox/streets-v9\"\n      containerStyle={{\n        height: '100%',\n        width: '100%'\n      }}\n    \u003e\n      \u003cLayer type=\"symbol\" id=\"marker\" layout={{ 'icon-image': 'marker-15' }}\u003e\n        \u003cFeature coordinates={[38.725670, -9.150370]} /\u003e\n      \u003c/Layer\u003e\n    \u003c/Map\u003e\n  )\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimaginary-cloud%2Freact-weather-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimaginary-cloud%2Freact-weather-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimaginary-cloud%2Freact-weather-app/lists"}