Skip to content

Latest commit

 

History

History
208 lines (130 loc) · 5.53 KB

File metadata and controls

208 lines (130 loc) · 5.53 KB

Plugin Development

Home

Previous: Publishing | Next: Architecture

This document explains how to add a new source plugin to nicegui-builder.

Goal

A plugin lets the library understand a new source type and translate it into:

  • form-oriented specs
  • collection-oriented specs
  • default widgets
  • optional rich rendering behaviors

Examples already present in the project:

  • pydantic for schema-driven forms
  • pandas for table-oriented collections

Mental Model

The core library should stay source-agnostic. A plugin is responsible for understanding a specific source and producing core-friendly specs.

Typical pipeline:

source -> plugin inspection -> specs -> widget resolution -> layout/rendering

Plugin Types

There are currently two practical plugin families.

Field Plugins

Field plugins power form(...).

They typically implement:

  • supports(source)
  • inspect_fields(source)
  • build_layout(source, flavor="")
  • build_field_context(model_class, model_instance, fieldname)
  • resolve_field_node(model_class, model_instance, fieldname, value)
  • resolve_widget(spec, variant="std")
  • optional render_form(source, flavor="")

See src/nicegui_builder/plugins/base.py.

Collection Plugins

Collection plugins power table(...).

They typically implement:

  • supports(source)
  • inspect_collection(source)
  • resolve_collection_widget(spec, variant="std")
  • optional render_collection(source, spec, variant="std")

Registration

Plugins are registered in the global plugin registry.

Minimal pattern:

from nicegui_builder.plugins.registry import plugin_registry


class MyPlugin:
    name = "my_plugin"

    def supports(self, source) -> bool:
        ...


my_plugin = MyPlugin()
plugin_registry.register(my_plugin)

Built-in plugins are typically registered from their package __init__.py.

What A Good Plugin Should Produce

For forms

Your plugin should produce FieldSpec values rich enough to support:

  • automatic widget choice
  • labels and descriptions
  • defaults
  • validation constraints
  • choices
  • plugin-specific metadata in source_meta

For collections

Your plugin should produce a CollectionSpec that describes:

  • columns
  • optional filter metadata
  • source-level metadata

Recommended Implementation Pattern

1. Start with supports(...)

Keep it strict and predictable. If the plugin cannot fully support the source, return False.

2. Build clean specs first

Prefer putting source understanding into FieldSpec and CollectionSpec instead of mixing it directly into rendering code.

3. Keep widget resolution separate

A plugin should usually have a dedicated resolution step from spec to widget intent.

For example:

  • YAML map for defaults
  • Python heuristics for richer cases

4. Use rich rendering only when it adds real value

Most plugins should let the generic builder do the rendering. Use render_form(...) or render_collection(...) only for behaviors that are meaningfully richer than generic rendering.

Current example:

  • the pandas plugin uses render_collection(..., variant="filters") for a richer filter UI

Pydantic Plugin Notes

The pydantic plugin is a good reference for form-oriented plugins.

Its code is organized under:

The YAML file is plugin-local on purpose, so the plugin stays self-contained.

One useful pattern in the pydantic plugin is the datetime split field. The resolver keeps date_input and time_input grouped as one logical field, while still allowing the layout node to override the wrapper container.

Example:

- field__starts_at:
    container: column
    classes: gap-2

This means the plugin can provide a rich field expansion without forcing a single visual wrapper such as row.

Pandas Plugin Notes

The pandas plugin is a good reference for collection-oriented plugins.

It shows how to:

  • inspect a DataFrame
  • infer column/filter metadata
  • provide default table widgets
  • optionally render a richer filtered table variant

See:

Testing Guidance

A plugin should usually be tested at three levels:

  1. supports(...)
  2. spec generation
  3. public entry point integration through form(...) or table(...)

Good tests are usually small and structural. You do not need a full NiceGUI runtime for most plugin tests.

Design Guidelines

  • Keep the core source-agnostic.
  • Prefer specs over ad hoc dictionaries.
  • Use source_meta for plugin-specific metadata.
  • Keep plugin-local maps and heuristics inside the plugin package.
  • Favor small rich render variants over plugin-wide custom rendering.
  • Preserve compatibility with the stable top-level API.

Future Plugin Candidates

Likely good additions:

  • dataclasses
  • json_schema
  • sqlmodel
  • sqlalchemy
  • polars

sqlmodel is especially interesting if the project later grows stronger persistence-aware CRUD workflows.