Firebase Studio allows you to rapidly prototype, build, and ship full-stack AI-infused apps quickly and efficiently, right from your browser. And in this post, we'll guide you through the process of building a weather app using Gemini.
Step 1: Gather your information
Before you start building your weather app, it's important to define the features you want to include. This can be included in a wireframe that covers elements such as input fields for city names, a search button, weather display sections based on geolocation, and error handling.
For this project, we’ll use the OpenWeatherMap API to get the current weather data and display it in the browser. The following information will be shown:
- City name
- Temperature
- Humidity
- Wind speed
- Weather description
- Weather condition
API Documentation: https://openweathermap.org/current#cityid
Step 2: Create your website content
Now it's time to create your website content. This involves providing Firebase Studio with a use case.
Generate a basic structure for a weather app. The core features for this app are included in the wireframe and should include:
- City Input: City Input Field: Allows users to enter a city name to request weather data.
- Search: Search Button: Triggers the weather fetch functionality with a clear, clickable button.
- Weather Display: Weather Display Sections: Displays current weather conditions such as temperature, humidity, wind speed, and weather description.
- Error Handling: Error Handling: Shows user-friendly error messages when a city is not found or when data cannot be retrieved.
When reviewing this content generated by Gemini, it's important to remember that you can fine-tune it as you go along.
It'll take about 1–2 minutes to generate the project along with all necessary dependencies, including React, TypeScript, NextJS, Tailwind CSS.
Step 3: Test your site
This project generated the following file structure with Mock API data for successful responses:
The mock api data can be found in the action.ts
file:
// Mock data for successful responses
const mockWeatherData: { [key: string]: WeatherData } = {
london: {
city: 'London',
temperature: 15.2,
humidity: 72,
windSpeed: 5.1,
description: 'scattered clouds',
iconName: 'Clouds',
},
paris: {
city: 'Paris',
temperature: 18.5,
humidity: 65,
windSpeed: 3.5,
description: 'clear sky',
iconName: 'Clear',
},
tokyo: {
city: 'Tokyo',
temperature: 22.0,
humidity: 80,
windSpeed: 2.0,
description: 'light rain',
iconName: 'Rain',
},
newyork: {
city: 'New York',
temperature: 25.0,
humidity: 60,
windSpeed: 7.0,
description: 'few clouds',
iconName: 'Clouds',
}
};
Mock data successfully displayed the relevant weather content in the browser, given the user enters one of the cities from the prompt, such as London, New York, or Tokyo.
Step 4: Modify your site
Next, you'll need to add the API key from OpenWeatherMap.org to your environment variables.
Secondly, you can modify the getWeather function in src/app/actions.ts using Gemini:
- Read the city list from src/app/city.list.json.
- Find the city ID based on the provided city name (The list can be downloaded from https://openweathermap.org/current#cityid).
- Make an API call to OpenWeatherMap using the city ID and the API key from the environment variables.
- Parse the API response and return the weather data in the desired format.
Note: OpenWeatherMap recommends calling the API by city ID to get unambiguous result for your city.
'use server';
import type { WeatherData, WeatherError, WeatherResponse } from '@/lib/types';
import cityList from './city.list.json';
// Mock API call - in a real app, this would fetch from OpenWeatherMap
export async function getWeather(
// biome-ignore lint/correctness/noUnusedVariables: parameter reserved for framework integration
_prevState: WeatherResponse | null,
formData: FormData
): Promise<WeatherResponse> {
const cityEntry = formData.get("city");
if (typeof cityEntry !== "string" || cityEntry.trim() === "") {
return { error: "Please enter a city name." };
}
const city = cityEntry.trim();
const openWeatherMapApiKey = process.env.OPENWEATHERMAP_API_KEY;
if (!openWeatherMapApiKey) {
console.error("OPENWEATHERMAP_API_KEY is not set in environment variables.");
return { error: "Server configuration error: API key missing.", city };
}
// Ensure cityList is available
if (typeof cityList === "undefined") {
return { error: "Internal error: city list is not available.", city };
}
const foundCity = cityList.find(c => c.name.toLowerCase() === city.toLowerCase());
if (!foundCity) {
return { error: `City "${city}" not found. Please check the spelling.`, city };
}
const cityId = foundCity.id;
const apiUrl = `https://api.openweathermap.org/data/2.5/forecast?id=${cityId}&appid=${openWeatherMapApiKey}&units=metric`;
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000); // 10s timeout
const response = await fetch(apiUrl, { signal: controller.signal });
clearTimeout(timeout);
if (!response.ok) {
const errorBody = await response.text();
console.error(`OpenWeatherMap API error: ${response.status} ${response.statusText}`, errorBody);
return { error: `Could not retrieve weather data: ${response.statusText}`, city };
}
const data = await response.json();
if (!Array.isArray(data.list) || data.list.length === 0) {
return { error: "Weather data is missing or malformed.", city };
}
const forecast = data.list[0];
if (
!forecast.main ||
!forecast.weather ||
!Array.isArray(forecast.weather) ||
forecast.weather.length === 0 ||
!forecast.wind
) {
return { error: "Incomplete weather information received.", city };
}
return {
city: foundCity.name,
temperature: forecast.main.temp,
humidity: forecast.main.humidity,
windSpeed: forecast.wind.speed,
description: forecast.weather[0].description,
iconName: forecast.weather[0].main,
};
} catch (error) {
if ((error as Error).name === "AbortError") {
return { error: "Weather data request timed out.", city };
}
console.error("Error fetching weather data:", error);
return { error: "An error occurred while fetching weather data.", city };
}
}
The final result is a successful response from the API returning the weather display based on the city name provided by the user.
Step 5: Launch your site
When you're satisfied with the result, you can launch your site and start showcasing your weather app to the world.
Github 👉 https://github.com/JavascriptDon/SkyCast
Live Demo 👉 https://sky-cast-three-plum.vercel.app/
Top comments (4)
pretty cool seeing the workflow laid out like this - tbh launching is always the real test for me, you think real-world feedback changes how folks actually build stuff long-term?
Its why i tried out firebase studio. Rapid Launch!
pretty cool seeing a start-to-finish build like this tbh, you think improvements come more from constantly shipping updates or getting real users to try it out and give you feedback?
A bit of both to be honest.
Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more