DEV Community

Cover image for Using External Weather Data In A Custom Panel Extension
Kevin Lewis for Directus

Posted on Originally published at docs.directus.io

Using External Weather Data In A Custom Panel Extension

In this post, you will learn how to fetch data from an external data source and display it in a custom panel extension for Directus Insights.

Panels can only talk to internal Directus services, and can't reliably make external web requests because browser security protections prevent these cross-origin requests from being made. To create a panel that can interact with external APIs, you will create bundle including an endpoint (that can make external requests) and a panel (that uses the endpoint).

Add an Extensions Volume

Follow our Directus Self-Hosted Quickstart, adding a volume for extensions:

volumes:
  - ./database:/directus/database
  - ./uploads:/directus/uploads
  - ./extensions:/directus/extensions // [!code ++]
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Create a Bundle

Once you have run docker compose up for the first time, local directories for the volumes will be created. Navigate to the extensions directory and use the Directus Extensions CLI to create a bundle:

npx create-directus-extension@latest
├ type: bundle
├ name: directus-extension-bundle-weather
└ language: javascript
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Then, navigate to the newly-created extension directory.

Create an Endpoint

Use npm run add to add a new extension to the bundle:

npm run add
├ type: endpoint
├ name: weather-endpoint
└ language: javascript
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Navigate to the new weather-endpoint/index.js file and replace it with the following:

export default {
    id: 'weather',
    handler: (router) => {
        router.get('/', async (req, res) => {
            try {
                const response = await fetch(`https://api.open-meteo.com/v1/forecast?current_weather=true&${req._parsedUrl.query}`);

                if (response.ok) {
                    res.json(await response.json());
                } else { 
                    res.status(response.status).send(response.statusText);
                }
            } catch(error) {
                res.status(500).send(error.message);
            }
        })
    }
}
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

From the directus-extension-bundle-weather directory, run npm run build. Restart your Directus project, and you should now be able to access http://localhost:8055/weather?longitude=0&latitude=0.

The Open-Meteo API requires a longitude and latitude, so they must always be provided.

Create a Panel

Use npm run add to add a new extension to the bundle:

npm run add
├ type: panel
├ name: weather-panel
└ language: javascript
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Navigate to the new weather-panel/index.js file, update the id to weather-panel and the name to Weather.

In the options array, remove the text field, and add two new fields for longitude and latitude:

options: [
    {
        field: 'longitude',
        name: 'Longitude',
        type: 'string',
        meta: {
            interface: 'input',
            width: 'half',
        },
    },
    {
        field: 'latitude',
        name: 'Latitude',
        type: 'string',
        meta: {
            interface: 'input',
            width: 'half',
        },
    },
],
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Open panel.vue, and at the top of the <script>, import useApi and Vue's ref:

import { useApi } from '@directus/extensions-sdk'; // [!code ++]
import { ref } from 'vue'; // [!code ++]

export default {
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Then, add longitude and latitude props:

props: {
    showHeader: {
        type: Boolean,
        default: false,
    },
    longitude: { // [!code ++]
        type: String,  // [!code ++]
        default: '0',  // [!code ++]
    },  // [!code ++]
    latitude: {  // [!code ++]
        type: String,  // [!code ++]
        default: '0',  // [!code ++]
    },  // [!code ++]
},
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Create a setup method which will run when the panel is loaded:

setup(props) {
    const api = useApi();
    const weather = ref({});

    async function fetchData() {
        const response = await api.get(`/weather?longitude=${props.longitude}&latitude=${props.latitude}`);
        weather.value = response.data;
    }
    fetchData();

    return { weather };
}
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

This code will immediately fetch weather data using the new internal endpoint, and then make it available as weather to the template.

Finally, update the template:

<template>
    <div class="text" :class="{ 'has-header': showHeader }">
        {{ text }}  // [!code --]
        {{ weather }}  // [!code ++]
    </div>
</template>
⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026 ⚽ Live Match: directus/using external weather data in a custom panel extension am - Info Live Streaming 2026

Run npm run build from the bundle directory, and restart Directus.

Use the Panel

Create a new Insights Dashboard and add a Weather panel. Add coordinates, and you should see external data displayed in the panel.

Panel configutation showing a longitude and latitude input field

A panel showing a JSON payload of weather data

You can now create panels using external data. If you have any questions at all, feel free to join our Discord community.

Top comments (0)