# How to Create Custom Model Templates for Local or Private Weather Data Sources in Herbie

> Learn to create custom model templates for local or private weather data in Herbie. Define a Python class in custom_template.py and integrate your unique data sources seamlessly.

- Repository: [Brian Blaylock/herbie](https://github.com/blaylockbk/herbie)
- Tags: how-to-guide
- Published: 2026-02-26

---

**You can create custom model templates for local or private weather data in Herbie by defining a Python class with a `template()` method in `~/.config/herbie/custom_template.py`, which Herbie automatically imports and makes available via the standard API.**

Herbie is an open-source Python package that simplifies downloading and processing GRIB2 weather model data. When working with proprietary datasets stored on private filesystems or behind firewalls, you need to create custom model templates for local or private weather data sources to integrate them into Herbie's workflow without modifying the core library.

## How Herbie Model Templates Work

Herbie loads model-specific file-path templates from classes defined in the `herbie.models` package. According to the source code in [`src/herbie/core.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/core.py) (lines 270-298), the core `Herbie` class calls `model_templates.<model>.template(self)` to obtain a dictionary mapping template keys to formatted file paths.

Each template class must implement a `template(self)` method that returns a dictionary. The dictionary keys represent different data sources (e.g., `"local_main"`), and the values are format strings that Herbie populates using object attributes like `self.model`, `self.date`, `self.nest`, `self.product`, and `self.fxx`.

## Setting Up Your Custom Template File

Herbie provides a dedicated location for user-defined templates that persists across package updates. The framework looks for a file named [`custom_template.py`](https://github.com/blaylockbk/herbie/blob/main/custom_template.py) in the user-wide configuration directory at `~/.config/herbie/` (as documented in [`src/herbie/models/local.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/models/local.py), line 15).

If this file does not exist when Herbie initializes, the library automatically generates a placeholder file containing `default_custom_template`. This behavior is implemented in [`src/herbie/__init__.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/__init__.py) (lines 111-167). The auto-generated file serves as a starting point that you can modify to define your own model classes.

## Defining a Custom Model Class

To create a working template, define a Python class in [`custom_template.py`](https://github.com/blaylockbk/herbie/blob/main/custom_template.py) that follows the structure demonstrated in [`src/herbie/models/local.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/models/local.py) (lines 41-59). The class must expose a `template` method that returns a dictionary with string values containing format placeholders.

Available attributes for formatting include:

- `self.model` – the model identifier
- `self.date` – the datetime object
- `self.fxx` – the forecast hour
- `self.nest` – the domain/nest identifier
- `self.product` – the product type

### Example: Private GRIB2 Dataset Template

Here is a complete example defining two custom models for local weather data:

```python

# ~/.config/herbie/custom_template.py

class MyLocalModel1:
    """Template for a private GRIB2 dataset stored on a local filesystem."""

    def template(self):
        return {
            "local_main": (
                f"/data/model1/{self.model}/grib/{self.date:%Y%m%d%H}"
                f"/nest{self.nest}/file.t{self.date:%H}z.{self.product}"
                f".f{self.fxx:02d}.grib2"
            )
        }

class MyLocalModel2:
    """Template for a second private dataset with alternative path structure."""

    def template(self):
        return {
            "local_main": (
                f"/alternative/path/model2/{self.model}/"
                f"{self.date:%Y%m%d%H}/nest{self.nest}/"
                f"run.t{self.date:%H}z.{self.product}.f{self.fxx:02d}.grib2"
            )
        }

```

## Using Custom Models with the Herbie API

Once you have defined your template classes in [`custom_template.py`](https://github.com/blaylockbk/herbie/blob/main/custom_template.py), Herbie automatically imports them during initialization via the logic in [`src/herbie/models/__init__.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/models/__init__.py) (lines 61-72). This makes your custom models available through the standard API without modifying the core library.

To access your local data, instantiate the `Herbie` class with the `model` parameter set to your custom class name:

```python
from herbie import Herbie

# Access the 0-hour forecast from the first custom model

h = Herbie(
    model="MyLocalModel1",          # class name defined in custom_template.py

    date="2024-07-15 12:00",       # any datetime compatible string

    fxx=0,                         # forecast hour

    product="prmsl",               # variable name as expected by the template

)

# Download the file (copies from the local path to Herbie's cache)

grib_path = h.download()

# Load into xarray for analysis

ds = h.xarray()
print(ds)

```

The `download()`, `xarray()`, and `plot()` methods function identically for custom templates because the core logic in [`src/herbie/core.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/core.py) treats all model templates uniformly. The only difference is that the file path resolves to your private filesystem location rather than a remote URL.

You can also access an alternative path from a second model:

```python
h2 = Herbie(
    model="MyLocalModel2",
    date="2024-07-15 12:00",
    fxx=6,
    product="tmp",
)

# The template resolves to the path defined in MyLocalModel2.template()

print(h2.path)   # shows the full file path on the private filesystem

```

## Summary

- Herbie loads model templates from Python classes that implement a `template()` method returning a dictionary of path format strings.
- Place your custom template definitions in `~/.config/herbie/custom_template.py` to persist them across package updates.
- The `template()` method can use any Herbie attribute (`self.date`, `self.fxx`, `self.product`, etc.) to construct file paths for local or private data sources.
- Herbie automatically imports custom templates during initialization, making them available via the standard `model="ClassName"` API.
- All Herbie methods (`download()`, `xarray()`, `plot()`) work unchanged with custom templates.

## Frequently Asked Questions

### Where does Herbie look for custom template files?

Herbie searches for a file named [`custom_template.py`](https://github.com/blaylockbk/herbie/blob/main/custom_template.py) in the user configuration directory at `~/.config/herbie/`. If the file does not exist, Herbie automatically creates a placeholder file containing `default_custom_template` during the first import, as implemented in [`src/herbie/__init__.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/__init__.py).

### What methods and attributes must a custom template class implement?

Your custom class must define a `template(self)` method that returns a dictionary mapping template keys to format strings. You can use any attribute that Herbie passes to the instance, including `self.model`, `self.date`, `self.fxx`, `self.nest`, and `self.product`, to construct the file path dynamically.

### Can I use Herbie's standard API methods with custom local templates?

Yes. Once you define your template class in [`custom_template.py`](https://github.com/blaylockbk/herbie/blob/main/custom_template.py), you can instantiate Herbie with `model="YourClassName"` and use `download()`, `xarray()`, and `plot()` exactly as you would with built-in models. The core logic in [`src/herbie/core.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/core.py) handles custom templates identically to remote data sources.

### Do I need to modify the Herbie source code to add custom templates?

No. The framework is designed specifically to avoid source code modifications. By placing your template definitions in `~/.config/herbie/custom_template.py`, Herbie imports them automatically during initialization via the logic in [`src/herbie/models/__init__.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/models/__init__.py), making your classes available alongside built-in templates.