Airflow Summit 2025 is coming October 07-09. Register now for early bird ticket!

Customize view of Apache from Airflow web UI

Airflow has feature that allows to integrate a custom UI along with its core UI using the Plugin manager.

Plugins integrate with the Airflow core RestAPI. In this plugin, three object references are derived from the base class airflow.plugins_manager.AirflowPlugin. They are fastapi_apps, fastapi_root_middlewares, external_views and react_apps.

Using fastapi_apps in Airflow plugin, the core RestAPI can be extended to support extra endpoints to serve custom static file or any other json/application responses. In this object reference, the list of dictionaries with FastAPI application and metadata information like the name and the url prefix are passed on.

Using fastapi_root_middlewares in Airflow plugin, allows to register custom middleware at the root of the FastAPI application. This middleware can be used to add custom headers, logging, or any other functionality to the entire FastAPI application, including core endpoints. In this object reference, the list of dictionaries with Middleware factories object, initialization parameters and some metadata information like the name are passed on.

Using external_views in Airflow plugin, allows to register custom views that are rendered in iframes or external link in the Airflow UI. This is useful for integrating external applications or custom dashboards into the Airflow UI. In this object reference, the list of dictionaries with the view name, href (templatable), destination and optional parameters like the icon and url_route are passed on.

Using react_apps in Airflow plugin, allows to register custom React applications that can be rendered in the Airflow UI. This is useful for integrating custom React components or applications into the Airflow UI. In this object reference, the list of dictionaries with the app name, bundle_url (where to load the js assets, templatable), destination and optional parameters like the icon and url_route are passed on.

Information and code samples to register fastapi_apps, fastapi_root_middlewares, external_views and react_apps are available in plugin.

Developing React Applications with the Bootstrap Tool

Airflow provides a React plugin bootstrap tool to help developers quickly create, develop, and integrate external React applications into the core UI. This is the most flexible and recommended way to customize the Airflow UI. This tool generates a complete React project structure that builds as a library compatible with dynamic imports and shares React instances with the host Airflow application.

Creating a New React Plugin Project

The bootstrap tool is located in dev/react-plugin-tools/ and provides a simple CLI to generate new React plugin projects:

# Navigate to the bootstrap tool directory
cd dev/react-plugin-tools

# Create a new plugin project
python bootstrap.py my-awesome-plugin

# Or specify a custom directory
python bootstrap.py my-awesome-plugin --dir /path/to/my-projects/my-awesome-plugin

This generates a complete React project with Vite, TypeScript, Chakra UI integration, and proper configuration for building as a library that integrates with Airflow’s UI.

React Development Workflow

Once your project is generated, refer to the README.md file in your project directory for complete development instructions, including:

  • Available development scripts (pnpm dev, pnpm build, etc.)

  • Project structure explanation

  • Development workflow with hot reload

  • Building for production

  • Troubleshooting common React development issues

The generated project is pre-configured with all necessary tools and follows Airflow’s UI development patterns.

Integrating with Airflow

To integrate your React application with Airflow, you need to:

  1. Serve the built assets you can do that on your own infrastructure or directly within Airflow using fastapi_apps

  2. Register the React app using react_apps plugin configuration

Example Plugin Implementation

Create an Airflow plugin that serves your React application:

from pathlib import Path
from fastapi import FastAPI
from starlette.staticfiles import StaticFiles
import mimetypes

from airflow.plugins_manager import AirflowPlugin

# Ensure proper MIME types for cjs files
mimetypes.add_type("application/javascript", ".cjs")

# Create FastAPI app to serve static files
app = FastAPI()

# Mount your React app's dist folder
react_app_directory = Path(__file__).parent.joinpath("my-awesome-plugin", "dist")
app.mount(
    "/my-react-app",
    StaticFiles(directory=react_app_directory, html=True),
    name="my_react_app_static",
)


class MyReactPlugin(AirflowPlugin):
    name = "My React Plugin"

    # Serve static files
    fastapi_apps = [
        {
            "app": app,
            "url_prefix": "/my-plugin",
            "name": "My Plugin Static Server",
        }
    ]

    # Register React application
    react_apps = [
        {
            "name": "My Awesome React App",
            "url_route": "my-awesome-app",
            "bundle_url": "http://localhost:28080/my-plugin/my-react-app/main.umd.cjs",
            "destination": "nav",
        }
    ]

Plugin Configuration Options

React apps support several configuration options, you can take a look at plugin for more details.

Integration Best Practices

The generated template follows these best practices for Airflow integration:

  1. External Dependencies: React and common libraries are marked as external to avoid conflicts with the host application

  2. Global Naming: Uses standardized global name (AirflowPlugin) for consistency

  3. Library Build: Configured as UMD library with proper externalization for dynamic imports

  4. MIME Types: Proper JavaScript MIME type handling for .cjs files because FastAPI serves them as plain text by default

Deployment Strategies

External Hosting

You can also host assets on external infrastructure:

react_apps = [
    {
        "name": "My External App",
        "url_route": "my-external-app",
        "bundle_url": "https://my-cdn.com/main.umd.cjs",
        "destination": "nav",
    }
]

Troubleshooting Integration Issues

Common integration issues and solutions:

MIME type issues

Ensure .js and .cjs files are served with correct MIME type using mimetypes.add_type("application/javascript", ".cjs").

Component not loading

Check that the bundle URL is accessible and matches the expected format.

React development issues

Refer to the README.md file generated with your project for detailed troubleshooting of React-specific development issues.

Support for Airflow 2 plugins

Airflow 2 plugins are still supported with some limitations. More information on such plugins can be found in the Airflow 2 documentation.

Adding Rest endpoints through the blueprints is still supported, those endpoints will be integrated in the FastAPI application via the WSGI Middleware and accessible under /pluginsv2.

Adding Flask-AppBuilder views ( appbuilder_views ) via the Airflow 2 is still supported in its own iframe.

It is not possible to extend the AF3 core UI, for instance by extending the base template, nonetheless extra menu items of the auth managers are added to the core UI security tab and their href are rendered in iframes. This is how the fab provider integrates users, roles, actions, resources and permissions custom views in the Airflow 3 UI.

Airflow 3 plugins will be improved to allow UI customization for the entire react app, it is recommended to upgrade your plugins to Airflow 3 plugins when possible. Until then for a temporary or custom needs it is possible to use a Middleware to inject custom javascript or css to the core UI index request.

Was this entry helpful?