Theme
Version
GitHub PyPI Discord
On this page

Registration

Before Citry can render <c-reading-list>, it needs to know which Python class that name means. Defining a component creates that connection. Once the class's module has been imported, every component on the same Citry instance can use its tag.

If importing every component module by hand becomes unwieldy, read Component discovery after this page.

Register a component when its class is defined

A concrete Component registers as soon as Python defines the class. There is no decorator or separate registration list:

from citry import Component, citry


class Greeting(Component):
    class Kwargs:
        name: str

    template = """
      <p>Hello, {{ name }}!</p>
    """


assert citry.get("greeting") is Greeting

Citry derives two case-insensitive names from a multiword class name:

  • ReadingList registers as readinglist and reading-list;
  • either <c-readinglist> or <c-reading-list> finds the same class.

A one-word name such as Greeting produces only greeting.

The c- prefix itself is always lowercase. The component-name suffix is case-insensitive, so <c-ReadingList> is valid, while <C-ReadingList> is not Citry component syntax.

Set name when the public tag should use a different name:

from citry import Component


class StatusBadge(Component):
    class Kwargs:
        text: str

    name = "result-badge"

    template = """
      <strong>{{ text }}</strong>
    """

The component is now available as <c-result-badge>.

Every component belongs to one Citry instance. Components without an explicit owner use the shared citry instance.

Applications often create their own instance so their components, settings, extensions, and routes stay together:

from citry import Citry, Component

app = Citry(autodiscover=False)


class ActionButton(Component):
    class Kwargs:
        label: str

    citry = app

    template = """
      <button type="button">{{ label }}</button>
    """


assert app.get("action-button") is ActionButton

A template resolves <c-*> tags through its own component's Citry instance. Two components can use each other's tags only when they belong to the same instance.

Add an alias when one class needs another name

Use register() to give an existing component another name on its own Citry instance:

app.register(ActionButton, name="primary-button")

assert app.get("primary-button") is ActionButton
assert app.has("action-button")

Aliases are useful when one application needs a local spelling. A reusable component package should publish a component library with deliberate public names.

Names must begin with a letter. The remaining characters may be letters, digits, hyphens, underscores, or dots. An invalid name raises ValueError.

If another component already owns the requested name, Citry raises AlreadyRegistered. Built-in and structural tag names are reserved and produce the same error. Looking up a name that does not exist raises NotRegistered.

Import the module before using its tag

Registration happens while Python executes the class statement. A class in a module that has never been imported does not exist yet, so its tag cannot be found.

For a small project, an ordinary import is enough:

from myproject.components.reading_list import ReadingList

The imported name does not need to appear elsewhere in that file. Running the module defines ReadingList, which registers its tag.

For a larger project, configure directories that Citry can import and prepare them during application startup. Component discovery shows the directory layout, explicit startup call, and recovery behavior.