User Docs Developer Docs | |

Getting Started

A Pubvana widget requires exactly two files. No PHP. No composer package. No service registration. Create the files, run Discover, and the widget appears in the admin Widgets area.

Step 1 — Create the Directory

Widget directories live at widgets/{your_slug}/. The folder name becomes the internal identifier. Use snake_case.

widgets/
  my_latest_quotes/
    widget_info.json
    views/
      widget.tpl

Step 2 — Write widget_info.json

{
    "name": "My Latest Quotes",
"description": "Displays recent quotes from the quotes table.",
    "version": "1.0.0",
    "min_pubvana_version": "2.2.3",
    "author": "Your Name",
    "admin": {
        "options": {
            "title": {"type": "text", "label": "Widget Title", "default": "Latest Quotes"},
            "count": {"type": "number", "label": "Number of Quotes", "default": "3"}
        }
    },
    "output": {
        "template": "widget.tpl",
        "providers": {
            "quotes": {
                "provider": "QuoteModel.getRecent",
                "params": {"limit": "count"}
            }
        }
    }
}

The slug field must match the directory name exactly. If they differ, discovery will fail silently.

Step 3 — Write views/widget.tpl

{% if quotes %}
<div class="{{ cls.cls_widget }}">
    {% if options.title %}
    <h3 class="{{ cls.cls_widget_title }}">{{ options.title }}</h3>
    {% endif %}
    <ul>
    {% for quote in quotes %}
        <li>{{ quote.body }} — <em>{{ quote.author }}</em></li>
    {% endfor %}
    </ul>
</div>
{% endif %}

Step 4 — Run Discover

In the admin panel: Appearance → Widgets → Discover Widgets. Pubvana scans all subdirectories of widgets/, parses widget_info.json files, and inserts new rows into the widgets table. Existing widget records are not overwritten.

Step 5 — Place the Widget

Go to Appearance → Widgets, find "My Latest Quotes" in the available list, and drag it into a widget area. Configure the options and save. The widget now renders on the front end wherever that widget area appears in the active theme.

Widget Without Data Providers

If your widget has no dynamic data (e.g. a static HTML block, a search form), omit the providers key entirely:

{
    "name": "Search Box",
"admin": {
        "options": {
            "title": {"type": "text", "label": "Placeholder Text", "default": "Search..."}
        }
    },
    "output": {
        "template": "widget.tpl"
    }
}

The template receives options but no provider-supplied variables.