# Render weather data from API function in a Markdoc tag

Build a custom Markdoc tag that renders live weather data by calling an API function.

This tutorial explains how to create:

- an API function endpoint at `/api/weather`
- a React component that fetches from that endpoint
- a Markdoc tag that authors can use in Markdown files


## Key concepts

**API functions** are server-side endpoints defined by adding TypeScript or JavaScript files inside the `@api` folder.
The filename determines the URL path and, optionally, the HTTP method: `<name>.<method>.ts` (for example, `weather.get.ts` maps to `GET /api/weather`).
Omit the method segment to handle all HTTP methods with a single file.
See [File-system and method routing](/docs/realm/customization/api-functions/api-functions-reference#file-system-and-method-routing) for the full naming reference.

**Markdoc tags** are custom components registered in the `@theme/markdoc` folder.
You create a React component in `@theme/markdoc/components/`, export it from `@theme/markdoc/components.tsx`, and register its tag schema in `@theme/markdoc/schema.ts`.
See [Build a Markdoc tag](/docs/realm/customization/build-markdoc-tags) for full details.

In the following solution:

- The **API key stays server-side** in the API function (`process.env.WEATHER_API_KEY`).
- The Markdoc component renders live data by calling your own endpoint.
- You can apply role-based access control to the API function.
See [API functions reference](/docs/realm/customization/api-functions/api-functions-reference).


## Before you begin

Make sure you have the following:

- familiarity with [building Markdoc tags](/docs/realm/customization/build-markdoc-tags)
- understanding of [API function basics](/docs/realm/customization/api-functions/api-functions-reference)
- a free API key from weatherapi.com exposed as `WEATHER_API_KEY` in your environment variables


## Create the Weather API function

Create the file `@api/weather.ts`.
This file defines an endpoint at `/api/weather` that accepts an optional query parameter `location`.
When `location` is omitted, the function falls back to the client's IP address for geolocation.

Import the `ApiFunctionsContext` type from `@redocly/config`.
This type provides TypeScript definitions for the context object passed to every API function.

Define types for the external weather API responses.
Typed responses improve editor support and catch integration errors early.

Export a default async function that receives a standard Web API Request and the Redocly context.

Access the API key from environment variables using `process.env`.
Return a `500` error early if the key is missing so the caller gets a clear message instead of a cryptic upstream failure.

Use the `location` query parameter if the caller provides one.
Otherwise, fall back to the client IP address from `x-forwarded-for` (or `auto:ip` as a last resort) so the weather API geolocates the visitor automatically.

Construct the URL for the external weather API and map your variables to the parameters required by the provider (e.g., mapping your `location` variable to their `q` parameter, and setting `aqi` to `no` to exclude Air Quality Index data).
Call the external weather API with `fetch`, and handle non-OK responses by returning the upstream error details.

Return the relevant subset of the weather data as JSON.
The Markdoc component will consume this shape.

## Create the Markdoc component

Create the file `@theme/markdoc/components/CurrentWeather.tsx`.
This React component fetches from your API function and renders the result.

Import React so you can use hooks and JSX.

Define the expected API response shape and component props.
The optional `location` prop lets authors specify a city; `units` chooses Celsius or Fahrenheit.

Declare the `CurrentWeather` function component with a state machine that tracks loading, error, and success states.

Use `useEffect` to call `/api/weather` when the component mounts.
If `location` is provided, pass it as a query parameter; otherwise omit it and let the API function resolve the location from the client IP.
An `AbortController` cancels the request if the component unmounts before the response arrives.

Render loading and error states first, then display the location, temperature, humidity, and wind speed.

## Register the Markdoc tag

Update `@theme/markdoc/schema.ts` to register a `weather` tag.
The `render` value must match the exported component name (`CurrentWeather`), and `selfClosing` means the tag has no children.
Both `location` and `units` are optional -- when `location` is omitted the API function geolocates the visitor by IP address.

Export `CurrentWeather` from `@theme/markdoc/components.tsx` so the Markdoc runtime can resolve the `render` value.

## Use the tag in Markdown

Authors can embed the `weather` tag in any `.md` file.

Geolocate the visitor by IP address:


```markdoc
{% weather /%}
```

Or specify a city explicitly:


```markdoc
{% weather location="London" units="celsius" /%}
```

## Resources

- **[Build a Markdoc tag](/docs/realm/customization/build-markdoc-tags)** - Create custom Markdoc tags with React components
- **[API functions reference](/docs/realm/customization/api-functions/api-functions-reference)** - Function signature, routing, context helpers, and access control