Overview
This guide will walk you through setting up and running the Weather Finder project, a beautiful weather forecast application that demonstrates React hooks, TypeScript, and API integration.
The Weather Finder app uses the free Open-Meteo API, so no API key is required. You can start building immediately!
Setup
Navigate to the project
From the repository root, navigate to the weather-finder directory:
Install dependencies
Install all required dependencies using pnpm: This will install React 19, TypeScript, Vite, and all development dependencies including testing libraries.
Start the development server
Launch the Vite development server: The app will be available at http://localhost:5173
Project Structure
The Weather Finder app is organized as follows:
weather-finder/
├── src/
│ ├── components/ # React components
│ ├── hooks/ # Custom React hooks
│ ├── services/ # API service layer
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Helper functions
│ ├── App.tsx # Main app component
│ └── main.tsx # Application entry point
├── package.json
└── vite.config.ts
Understanding the Code
Main App Component
The App.tsx file demonstrates React best practices:
import { useWeather } from './hooks/useWeather' ;
import { SearchBar } from './components/SearchBar' ;
import { CurrentWeather } from './components/CurrentWeather' ;
import { WeatherForecast } from './components/WeatherForecast' ;
import { LoadingSpinner } from './components/LoadingSpinner' ;
import { ErrorMessage } from './components/ErrorMessage' ;
import './App.css' ;
function App () {
const { status , data , error , search , savedCity } = useWeather ();
return (
< div className = "app" >
< header className = "app-header" >
< h1 className = "app-title" >
< span aria-hidden = "true" > 🌤️ </ span > Weather Finder
</ h1 >
< p className = "app-subtitle" > Consulta el clima de cualquier ciudad del mundo </ p >
</ header >
< main className = "app-main" >
< SearchBar
onSearch = { search }
isLoading = { status === 'loading' }
initialValue = { savedCity }
/>
< div className = "app-content" >
{ status === 'idle' && (
< div className = "idle-state" >
< span className = "idle-emoji" aria-hidden = "true" > 🌍 </ span >
< p > Busca una ciudad para ver su pronóstico del tiempo </ p >
</ div >
) }
{ status === 'loading' && < LoadingSpinner /> }
{ status === 'error' && error && < ErrorMessage message = { error } /> }
{ status === 'success' && data && (
<>
< CurrentWeather data = { data } />
< WeatherForecast daily = { data . daily } />
</>
) }
</ div >
</ main >
</ div >
);
}
export default App ;
Custom Hook: useWeather
The app uses a custom hook to manage weather data and API calls:
import { useState , useCallback , useEffect } from 'react' ;
import { geocodeCity , fetchWeather } from '../services/api' ;
import type { WeatherData , Status } from '../types/weather' ;
const LAST_CITY_KEY = 'weather-finder:last-city' ;
export function useWeather () {
const [ savedCity ] = useState < string >(() =>
localStorage . getItem ( LAST_CITY_KEY ) ?? ''
);
const [ state , setState ] = useState < WeatherState >({
status: 'idle' ,
data: null ,
error: null ,
});
const search = useCallback ( async ( city : string ) => {
const trimmed = city . trim ();
if ( ! trimmed ) return ;
setState ({ status: 'loading' , data: null , error: null });
try {
const { name , latitude , longitude , country } = await geocodeCity ( trimmed );
const { current , daily } = await fetchWeather ( latitude , longitude );
localStorage . setItem ( LAST_CITY_KEY , trimmed );
setState ({
status: 'success' ,
data: { cityName: name , country , current , daily },
error: null ,
});
} catch ( err ) {
setState ({
status: 'error' ,
data: null ,
error: err instanceof Error ? err . message : 'Ocurrió un error inesperado.' ,
});
}
}, []);
// Auto-search the last city on mount
useEffect (() => {
const lastCity = localStorage . getItem ( LAST_CITY_KEY );
if ( lastCity ) search ( lastCity );
}, [ search ]);
return { ... state , search , savedCity };
}
This custom hook demonstrates several React patterns:
State management with useState
Async operations with useCallback
Side effects with useEffect
LocalStorage persistence
Proper error handling
Available Commands
Here are all the commands you can use:
Development
Build
Preview
Lint
Test
pnpm dev
# Starts the Vite dev server with hot module replacement
Testing Your Changes
The project includes Vitest for testing. Run the test suite:
For watch mode during development:
Tests are located in the src/test/ directory and use @testing-library/react for component testing.
Building for Production
When you’re ready to deploy:
Build the project
This runs TypeScript compilation followed by Vite’s production build.
Preview the build
Test the production build locally:
Deploy
The dist/ folder contains your production-ready files. Deploy to any static hosting service: # Example: Deploy to Vercel
pnpm add -g vercel
vercel login
vercel --prod
Make sure to test your production build with pnpm preview before deploying to catch any build-specific issues.
Key Features to Explore
1. City Search with Geocoding
Type any city name to get weather data. The app uses the Open-Meteo Geocoding API to convert city names to coordinates.
2. Current Weather Display
See real-time weather conditions including temperature, humidity, wind speed, and weather codes.
3. 7-Day Forecast
View a weekly forecast with daily temperature ranges and weather conditions.
4. LocalStorage Persistence
The app remembers your last searched city and automatically loads it on return visits.
5. Responsive Design
Fully responsive layout that works beautifully on mobile, tablet, and desktop.
Try the Other Projects
Once you’re comfortable with Weather Finder, explore the other projects:
Gifs App Learn about API integration with Giphy, state management for search history, and grid layouts. cd ../gifs-app
pnpm install && pnpm dev
Hooks App Study React hooks in isolation with practical examples like a traffic light component. cd ../hooks-app
pnpm install && pnpm dev
Next Steps
Weather Finder Project Explore the Weather Finder project in detail
API Integration Deep dive into how the Open-Meteo API integration works
Custom Hooks Learn about custom hooks like useWeather and useGifs
Component Patterns Explore reusable component patterns and best practices
Troubleshooting
Port Already in Use
If port 5173 is already in use, Vite will automatically try the next available port. You can also specify a custom port:
Dependencies Issues
If you encounter dependency resolution issues:
rm -rf node_modules pnpm-lock.yaml
pnpm install
TypeScript Errors
Make sure your editor is using the workspace TypeScript version:
For VS Code users, press Cmd/Ctrl + Shift + P and select “TypeScript: Select TypeScript Version” → “Use Workspace Version”
Get Help
If you run into issues:
Check the GitHub Issues
Review the project README files
Open a new issue with details about your problem