Adding a new input/output type
The most common Pixie contribution. The renderer is intentionally boring — adding a new type is four files.
Workflow
import { Steps } from “@astrojs/starlight/components”;
-
Add the Pydantic class in
pixie/discovery.py. Inherit from_InputBaseor the appropriate output base.class FrequencyInput(_InputBase):type: Literal["frequency"]min_hz: float = 20.0max_hz: float = 20000.0step: float = 1.0unit: str = "Hz"Add it to the discriminated union:
InputSpec = Annotated[Union[TextInput, NumberInput, ...,FrequencyInput,],Field(discriminator="type"),] -
Add the partial. For an input,
pixie/templates/partials/inputs/frequency.html:{%- from "partials/inputs/_macros.html" import field_open, field_close -%}{{ field_open(spec, field_id) }}<div class="input-row" x-data='{ value: {{ initial_json }} }'><input type="range"id="{{ field_id }}"name="{{ spec.key }}"min="{{ spec.min_hz }}"max="{{ spec.max_hz }}"step="{{ spec.step }}"x-model.number="value"class="range" /><output class="t-meta" x-text="value + ' {{ spec.unit }}'"></output></div>{{ field_close(spec) }}For an output, follow the shape of an existing
templates/partials/outputs/<type>.htmland use theoutput_cardmacro. -
Add the dispatch entry so the renderer knows about the new type. In
pixie/renderer/inputs.py(oroutputs.py):PARTIAL["frequency"] = "inputs/frequency.html"For outputs that need a required value shape (most non-scalar outputs), also add to
_OUTPUT_OBJECT_REQUIREMENTSinpixie/validator.py:_OUTPUT_OBJECT_REQUIREMENTS["spectrogram"] = ("data", "sample_rate") -
Add a sample-input rule so the validator can synthesise a value when no
defaultis given. Inpixie/validator.py:_INPUT_DEFAULTS["frequency"] = lambda spec: (spec.min_hz + spec.max_hz) / 2 -
Add a test fixture under
tests/fixtures/types/containing a minimal tool that exercises the new type, then a test intests/unit/test_renderer_inputs.py(or outputs).
That’s the whole workflow. The renderer is decoupled enough that you should never need to touch the existing types when adding a new one.
Naming conventions
- Input/output type names are snake_case (
map_polygon,chart_scatter). - Keep them short and concrete (
frequency, notaudio_frequency_picker). - If the type would naturally pair with a sibling, name it accordingly
(
chart_line/chart_area,map_points/map_heatmap).
When NOT to add a type
- One-off needs. If only one tool would use it, add a
jsoninput with aschemaand let the tool parse — don’t bloat the renderer. - Tiny variations. A “small text” vs “big text” distinction is a CSS class, not a type.
- Validation logic.
numberwithmin/maxis fine. Don’t add apositive_numbertype. - Display tweaks on outputs.
formatandprecisiononnumberexist for a reason. Use them.
The 25 input types and 39 output types we have today cover ~99% of imaginable tools. Adding a new one should require a clear story for at least two tools that need it.
After you add a type
- Update Input types or Output types in the docs site (this repo).
- If you added a chart type, update the docs’
pixie.jsmention of Plotly in Concepts → Schema-driven UI. - Mention it in the PR description as “new type: …”. Reviewers will look for the four-file pattern above.