# How to Build a Custom Weather Module for Waybar

If you are customizing your Linux desktop environment, perhaps using a window manager like Hyprland or Sway, you are likely using **Waybar**. While Waybar has many great built-in modules, sometimes you need something lighter or more specific than the defaults.

One common request we see is a simple weather display. Instead of relying on heavy external programs, we can build a highly efficient custom module using a basic Bash script and the free OpenWeatherMap API.

By the end of this guide, you will have a clean weather module on your bar showing the current temperature and an emoji icon matching the current conditions, like this: **☀️ 33°F**.

<Image class="m-auto" src={waybar} alt="building llms for production" />

_What, are you not jammin' to the 80s also?_

### Prerequisites

Before we begin, ensure you have the necessary tools installed on your system. We need a way to fetch data (`curl`) and a way to parse JSON data (`jq`).

On Arch Linux:

```bash
sudo pacman -S curl jq
```

On Debian/Ubuntu based systems:

```bash
sudo apt install curl jq
```

### Step 1: Get Your OpenWeatherMap API Key

To get weather data, we need an API key.

1.  Go to [OpenWeatherMap.org](https://openweathermap.org/) and sign up for a free account.
2.  Navigate to your API Keys tab and generate a new key. _Note: It can take 10–30 minutes for a new key to become active._
3.  In the meantime head over to [LatLong.net](https://www.latlong.net/) and search for your city on their website. You will need the **Latitude** and **Longitude** from the URL for the script below.

### Step 2: Create the Weather Script

We need a script that fetches the raw weather data and formats it into JSON that Waybar understands. Waybar expects a JSON output containing at least a `"text"` field (what shows on the bar) and optionally a `"tooltip"` field (what shows when you hover).

Create a new directory for your scripts if you haven't already, and create the file (use your dotfiles instead if you prefer):

```bash
mkdir -p ~/.config/waybar/scripts
touch ~/.config/waybar/scripts/weather.sh
chmod +x ~/.config/waybar/scripts/weather.sh
```

Open `weather.sh` in your text editor and paste the following script. **Be sure to update the Configuration section at the top with your API key and coordinates.**

```bash
#!/bin/bash

# --- CONFIGURATION ---
API_KEY="YOUR_ACTUAL_API_KEY_HERE" # Paste your key here
LAT="40.712776"  # Replace with your Latitude
LON="-74.005974" # Replace with your Longitude
UNITS="imperial" # Use "metric" for Celsius, "imperial" for Fahrenheit
# ---------------------

# Validate configuration
if [ -z "$LAT" ] || [ -z "$LON" ] || [ -z "$UNITS" ] || [ -z "$API_KEY" ]; then
    echo "Config missing"
    exit 1
fi

# Fetch the weather data
RESPONSE=$(curl -s "[https://api.openweathermap.org/data/2.5/weather?lat=$](https://api.openweathermap.org/data/2.5/weather?lat=$){LAT}&lon=${LON}&appid=${API_KEY}&units=${UNITS}")

# Check if curl failed to get a response
if [ -z "$RESPONSE" ]; then
    echo "No connection"
    exit 1
fi

# 1. Get the Temperature
# We use jq's built-in 'round' function to avoid ugly decimals (e.g., 71.6°F becomes 72°F)
TEMP=$(echo "$RESPONSE" | jq '.main.temp | round')

# 2. Get the Description (for the tooltip)
DESC=$(echo "$RESPONSE" | jq -r '.weather[0].description')

# 3. Get the Icon Code and map it to an emoji
ICON_CODE=$(echo "$RESPONSE" | jq -r '.weather[0].icon')

case $ICON_CODE in
    "01d") ICON="☀️";;  # Clear sky day
    "01n") ICON="🌙";;  # Clear sky night
    "02d") ICON="⛅";;  # Few clouds day
    "02n") ICON="☁️";;  # Few clouds night
    "03d"|"03n") ICON="☁️";; # Scattered clouds
    "04d"|"04n") ICON="☁️";; # Broken clouds
    "09d"|"09n") ICON="🌧️";; # Shower rain
    "10d") ICON="🌦️";; # Rain day
    "10n") ICON="🌧️";; # Rain night
    "11d"|"11n") ICON="⛈️";; # Thunderstorm
    "13d"|"13n") ICON="❄️";; # Snow
    "50d"|"50n") ICON="🌫️";; # Mist
    *) ICON="❓";;      # Default
esac

# Determine unit label
if [ "$UNITS" = "metric" ]; then
    LABEL="°C"
else
    LABEL="°F"
fi

# Final JSON output for Waybar
echo "{\"text\": \"${ICON} ${TEMP}${LABEL}\", \"tooltip\": \"${DESC}\"}"
```

#### Test the Script

Before moving to Waybar configurations, run the script manually in your terminal to ensure it works:

```bash
~/.config/waybar/scripts/weather.sh
```

You should see an output similar to this:
`{"text": "☀️ 72°F", "tooltip": "clear sky"}`

### Step 3: Configure Waybar

Now we need to tell Waybar how to use this script. Open your main configuration file (usually `~/.config/waybar/config` or `config.jsonc`).

Add the following block anywhere in your module definitions.

```jsonc
"custom/weather": {
    "format": "{}",
    "interval": 600, // Update every 10 minutes (600 seconds)
    "exec": "~/.config/waybar/scripts/weather.sh", // or your dotfiles folder if you use stow
    "return-type": "json",
}
```

### Step 4: Add the Module to Your Layout

Simply defining the module doesn't make it appear. You must add it to your layout arrays (`modules-left`, `modules-center`, or `modules-right`).

Find where you want it to appear in your `config.jsonc` and add `"custom/weather"`.

```jsonc
    "modules-right": [
    "pulseaudio",
    "network",
    "custom/weather", // <-- Add this line here
    "clock"
],
```

Save your configuration file. If your Waybar is set to auto-reload, the weather should appear shortly! Otherwise manually restart Waybar.

Finally, update your CSS to space it out accordingly.

### Troubleshooting Common Issues

If nothing shows up on your bar, don't panic. It's usually one of two very common mistakes made during configuration:

#### 1. The Typo Trap

In Step 3, we named the module definition block `"custom/weather"`.
In Step 4, when adding it to the layout list, you must use that exact name.

A common mistake is typing `"custom-weather"` (with a dash) in the layout list instead of `"custom/weather"` (with a slash). Waybar won't recognize the name with the dash and will display nothing.

#### 2. The Incorrect File Path

If your script works manually in the terminal but not in Waybar, Waybar likely cannot find the file.

Double-check the `"exec"` line in your config. If your actual script lives in a specific dotfiles folder structure (e.g., `~/dotfiles/waybar/scripts/weather.sh`), your config must point to that exact path, not the generic `~/.config/...` path, unless you have symlinks set up correctly.