# How to Extend SQuADDS with Custom Component Types Beyond Built-in Qubits and Cavities

> Learn to extend SQuADDS with custom component types beyond qubits and cavities. Create new QComponent subclasses and integrate them into your designs easily.

- Repository: [Levenson-Falk Lab/squadds](https://github.com/lfl-lab/squadds)
- Tags: how-to-guide
- Published: 2026-03-06

---

**You can extend SQuADDS by creating a new `QComponent` subclass in `squadds/components/`, exposing it in [`squadds/components/__init__.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/components/__init__.py), optionally registering the short name in [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py), and instantiating it in your designs or the WebUI.**

SQuADDS builds every quantum device from modular `QComponent` subclasses that reside in the `squadds/components` package. While the library ships with built-in types like `QubitCavity` and `CavityClaw`, extending SQuADDS with custom component types such as resonators, filters, or couplers requires only four straightforward steps. This guide demonstrates the exact file locations, method signatures, and code patterns needed to add a λ/4 CPW resonator to your workflow.

## Creating a Custom QComponent Subclass

Every device in SQuADDS inherits from `QComponent`, which provides the geometry engine integration. To extend SQuADDS with custom component types, you must define a new subclass that specifies default options, component metadata, and a `make()` method.

### Component Structure and Required Methods

A valid SQuADDS component requires three specific elements:

- **`default_options`** – A `Dict` containing default geometric and positional parameters (e.g., `trace_width`, `pos_x`).
- **`component_metadata`** – A `Dict` containing a `short_name` key used by the database to build dataset identifiers.
- **`make()`** – The method that constructs the geometry using Qiskit-Metal primitives.

In [`squadds/components/quarter_wave_resonator.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/components/quarter_wave_resonator.py), the `QuarterWaveResonator` class demonstrates this structure by wrapping a `RouteMeander` primitive to create a resonant CPW structure.

### Example: Building a Quarter-Wave Resonator

Create the file [`squadds/components/quarter_wave_resonator.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/components/quarter_wave_resonator.py) with the following implementation:

```python

# File: squadds/components/quarter_wave_resonator.py

from qiskit_metal import Dict
from qiskit_metal.qlibrary.core import QComponent
from qiskit_metal.qlibrary.tlines.meandered import RouteMeander

class QuarterWaveResonator(QComponent):
    """
    Simple λ/4 coplanar waveguide resonator.
    """

    default_options = Dict(
        chip="main",
        length="4000um",            # total resonator length (≈ λ/4 at 5 GHz on typical substrates)

        trace_width="10um",
        trace_gap="6um",
        orientation=0,               # degrees

        pos_x="0um",
        pos_y="0um",
    )
    component_metadata = Dict(short_name="quarter_res")
    """Component metadata – used for naming in the DB."""

    def make(self):
        """Create the CPW resonator using Qiskit‑Metal primitives."""
        p = self.p
        # Create a straight CPW of the requested length

        self.resonator = RouteMeander(
            self.design,
            f"{self.name}_res",
            options=Dict(
                total_length=p.length,
                trace_width=p.trace_width,
                trace_gap=p.trace_gap,
                orientation=p.orientation,
                start_anchor=self.position,
            ),
        )

```

Key implementation details include inheriting from `QComponent`, wrapping options in the `Dict` class as used throughout SQuADDS, and providing the `short_name` metadata that [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py) uses for dataset naming logic.

## Registering Your Component in the SQuADDS Package

After defining the class, you must expose it at the package level so other modules can resolve the import. Edit [`squadds/components/__init__.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/components/__init__.py) to include your new component:

```python

# File: squadds/components/__init__.py

from .quarter_wave_resonator import QuarterWaveResonator  # <-- expose the new component

# Existing imports (e.g. QubitCavity, CavityClaw, Airbridge) stay unchanged

```

Now `QuarterWaveResonator` can be imported directly as `from squadds.components import QuarterWaveResonator`.

## Integrating with the Database and WebUI

To make your custom component appear automatically in UI selectors and dataset naming logic, add its `short_name` to the list returned by `supported_components()` in [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py).

```python

# File: squadds/core/db.py (excerpt)

def supported_components(self):
    """Return list of component names recognized by SQuADDS."""
    # Existing logic reads config names; we augment it manually for a custom component.

    components = [c for c in self._components_from_configs()]
    if "quarter_res" not in components:
        components.append("quarter_res")   # <-- Add our custom short name

    return components

```

The `supported_components()` method is consumed by [`squadds/ui/app.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/ui/app.py) to populate dropdown menus and by the dataset-naming helpers in [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py). Adding the short name guarantees the component appears in the WebUI under *“Component Type”* without requiring a full config entry.

## Using Custom Components in Simulations and Workflows

Once registered, instantiate your component exactly like built-in types. The simulation utilities in [`squadds/simulations/objects.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/simulations/objects.py) and [`squadds/simulations/utils.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/simulations/utils.py) accept any `QComponent` subclass, so your custom type works out-of-the-box for electromagnetic simulations and GDS export.

```python

# Example script (run inside a SQuADDS environment)

import squadds
from squadds.components import QuarterWaveResonator

# Initialise a design (the same as other examples)

design = squadds.Design(name="my_resonator")

# Create the component

res = QuarterWaveResonator(design, "Res1")

# Render to GDS (optional)

res.to_gds("my_resonator", include_wirebond_pads=False)

```

When you start the WebUI (`uv run python -m squadds.ui.app`), selecting *“quarter_res”* from the dropdown automatically invokes the `make()` method defined in your subclass.

## Summary

- **Create** a subclass of `QComponent` with `default_options`, `component_metadata` (including `short_name`), and a `make()` method that builds geometry using Qiskit-Metal primitives.
- **Expose** the class by importing it in [`squadds/components/__init__.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/components/__init__.py) to make it available throughout the package.
- **Register** the `short_name` in [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py)’s `supported_components()` method to enable UI dropdowns and dataset naming.
- **Instantiate** the component in scripts or the WebUI; it integrates automatically with simulation helpers in [`squadds/simulations/objects.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/simulations/objects.py) and [`squadds/simulations/utils.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/simulations/utils.py).

## Frequently Asked Questions

### How do I make my custom component appear in the SQuADDS WebUI dropdown?

Add the component’s `short_name` (defined in `component_metadata`) to the list returned by `supported_components()` in [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py). The WebUI in [`squadds/ui/app.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/ui/app.py) reads this list to populate the *“Component Type”* selector, so no modifications to the UI code itself are required.

### What Qiskit-Metal primitives can I use inside the `make()` method?

You can use any Qiskit-Metal object from `qiskit_metal.qlibrary`, such as `RouteMeander`, `Rectangle`, or `CircleCute`. The `make()` method simply needs to instantiate these primitives and attach them to `self.design`, allowing you to build complex geometries including meandered resonators, airbridges, or 3D blocks.

### Will custom components work with SQuADDS simulation tools if I don't modify [`db.py`](https://github.com/lfl-lab/squadds/blob/main/db.py)?

Yes. The simulation utilities in [`squadds/simulations/objects.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/simulations/objects.py) and [`squadds/simulations/utils.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/simulations/utils.py) accept any `QComponent` instance regardless of registration status. However, omitting the `supported_components()` registration means the component will not appear in WebUI dropdowns and may not be recognized by dataset-naming logic in [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py).

### Do I need to create a configuration file to add a new component type?

No. While SQuADDS supports config-driven component definitions, you can manually extend the system by directly editing [`squadds/components/__init__.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/components/__init__.py) and [`squadds/core/db.py`](https://github.com/lfl-lab/squadds/blob/main/squadds/core/db.py) as shown above. This approach is ideal for rapid prototyping of single custom elements like λ/4 resonators or specialized couplers.