Skip to content

Component Registry

Faststrap registers public components with lightweight metadata so humans, CLIs, and AI agents can discover what already exists before inventing new wrappers.

Why It Exists

  • Discover components by category or search text.
  • Check whether a component requires Bootstrap JavaScript.
  • Build documentation, tooling, or agent workflows from the same public component inventory.
  • Keep custom components discoverable when you use the @register decorator.

Quick Start

from faststrap import find_components, list_components, list_component_metadata

display_components = list_components(category="display")
card_like = find_components("card")

for meta in list_component_metadata(category="feedback"):
    print(meta["name"], meta["requires_js"])

Categories

The built-in registry categories are:

Category Typical components
forms Button, Input, FormGroup, InlineEditor
display Card, DataTable, Avatar, MetricCard
feedback Alert, Modal, Toast, ModernToast
navigation Navbar, Tabs, CommandPalette, Pagination
layout Container, Row, Col, Hero
patterns FeatureGrid, PricingGroup, NavbarModern

Functions

list_components(category=None)

Return registered component names. Pass a category to filter the list.

from faststrap import list_components

all_names = list_components()
forms = list_components(category="forms")

find_components(query, category=None)

Search component names, categories, modules, and docstrings using a case-insensitive substring match.

from faststrap import find_components

find_components("toast")
find_components("card", category="display")

get_component(name)

Return a component callable by name, or None if no component is registered under that name.

from faststrap import get_component

Modal = get_component("Modal")
if Modal is not None:
    modal = Modal("Body", title="Loaded dynamically")

get_components_by_pattern(pattern, category=None)

Return component callables whose registry text matches a query. This is useful for agent/tool workflows that need to inspect and reuse existing components.

from faststrap import get_components_by_pattern

for component in get_components_by_pattern("metric"):
    print(component.__name__)

list_component_metadata(category=None)

Return metadata dictionaries for every registered component.

from faststrap import list_component_metadata

metadata = list_component_metadata(category="navigation")

Common metadata keys:

Key Type Description
name str Registered component name.
category str \| None Registry category.
requires_js bool Whether Bootstrap JavaScript is needed.
bootstrap_version str Minimum Bootstrap version recorded by the component.
module str Python module where the component is defined.
doc str \| None Component docstring.
func Callable Original component function.

Registering Custom Components

Use @register when a custom component should be discoverable by tooling.

from typing import Any

from fasthtml.common import Div
from faststrap import register


@register(category="display", requires_js=False)
def ProductCard(*children: Any, **kwargs: Any) -> Div:
    return Div(*children, cls="product-card", **kwargs)

API Reference

faststrap.core.registry.register(name=None, category=None, bootstrap_version='5.3.3', requires_js=False)

Decorator to register component metadata. Args: name: Component name (defaults to function name) category: Component category (layout, display, etc.) bootstrap_version: Min Bootstrap version required requires_js: Whether component needs Bootstrap JS Examples: >>> @register(category="feedback", requires_js=True) >>> def Modal(...): ...

Source code in src/faststrap/core/registry.py
def register(
    name: str | None = None,
    category: str | None = None,
    bootstrap_version: str = "5.3.3",
    requires_js: bool = False,
) -> Callable[[F], F]:
    """Decorator to register component metadata.
    Args:
        name: Component name (defaults to function name)
        category: Component category (layout, display, etc.)
        bootstrap_version: Min Bootstrap version required
        requires_js: Whether component needs Bootstrap JS
    Examples:
        >>> @register(category="feedback", requires_js=True)
        >>> def Modal(...): ...
    """

    def decorator(func: F) -> F:
        component_name = name or func.__name__

        _component_registry[component_name] = {
            "func": func,
            "category": category,
            "bootstrap_version": bootstrap_version,
            "requires_js": requires_js,
            "module": func.__module__,
            "doc": func.__doc__,
        }

        # Mark function as registered (Ruff B010 requires 'noqa', MyPy requires 'type: ignore')
        # fmt: off
        setattr(func, "__faststrap_registered__", True)  # noqa: B010 # type: ignore[attr-defined]
        setattr(func, "__faststrap_metadata__", _component_registry[component_name])  # noqa: B010 # type: ignore[attr-defined]
        # fmt: on

        return func

    return decorator

faststrap.core.registry.list_components(category=None)

List all registered components, optionally filtered by category. Args: category: Filter by category (layout, display, feedback, etc.) Returns: List of component names Examples: >>> list_components(category="feedback") ['Alert', 'Toast', 'Modal', 'Spinner']

Source code in src/faststrap/core/registry.py
def list_components(category: str | None = None) -> list[str]:
    """List all registered components, optionally filtered by category.
    Args:
        category: Filter by category (layout, display, feedback, etc.)
    Returns:
        List of component names
    Examples:
        >>> list_components(category="feedback")
        ['Alert', 'Toast', 'Modal', 'Spinner']
    """
    ensure_autodiscovered()

    if category is None:
        return list(_component_registry.keys())

    return [name for name, meta in _component_registry.items() if meta.get("category") == category]

faststrap.core.registry.find_components(query, *, category=None)

Find components by name, category, module, or docstring text.

Source code in src/faststrap/core/registry.py
def find_components(
    query: str,
    *,
    category: str | None = None,
) -> list[str]:
    """Find components by name, category, module, or docstring text."""
    ensure_autodiscovered()
    normalized = query.casefold().strip()
    if not normalized:
        return list_components(category=category)

    matches = []
    for name, meta in _component_registry.items():
        if category is not None and meta.get("category") != category:
            continue
        haystack = " ".join(
            [
                name,
                str(meta.get("category") or ""),
                str(meta.get("module") or ""),
                str(meta.get("doc") or ""),
            ]
        ).casefold()
        if normalized in haystack:
            matches.append(name)
    return matches

faststrap.core.registry.get_component(name)

Get component function by name.

Source code in src/faststrap/core/registry.py
def get_component(name: str) -> Callable[..., Any] | None:
    """Get component function by name."""
    ensure_autodiscovered()
    return _component_registry.get(name, {}).get("func")

faststrap.core.registry.get_components_by_pattern(pattern, *, category=None)

Return component callables matching a pattern.

This is a convenience API for agents and app builders that need to discover existing components before inventing new UI.

Source code in src/faststrap/core/registry.py
def get_components_by_pattern(
    pattern: str, *, category: str | None = None
) -> list[Callable[..., Any]]:
    """Return component callables matching a pattern.

    This is a convenience API for agents and app builders that need to discover
    existing components before inventing new UI.
    """
    return [
        component
        for name in find_components(pattern, category=category)
        if (component := get_component(name)) is not None
    ]

faststrap.core.registry.list_component_metadata(category=None)

List registered component metadata records.

Parameters:

Name Type Description Default
category str | None

Optional category filter.

None

Returns:

Type Description
list[dict[str, Any]]

Metadata dictionaries with a stable name key added.

Source code in src/faststrap/core/registry.py
def list_component_metadata(category: str | None = None) -> list[dict[str, Any]]:
    """List registered component metadata records.

    Args:
        category: Optional category filter.

    Returns:
        Metadata dictionaries with a stable ``name`` key added.
    """
    ensure_autodiscovered()
    records = []
    for name, meta in _component_registry.items():
        if category is not None and meta.get("category") != category:
            continue
        records.append({"name": name, **meta})
    return records