Skip to main content

discomposer for discord.py

Validate, fetch and send Discord message templates as Components V2.
Design the message in the visual editor, send it from your bot with a code.

Website · Editor · Documentation

PyPI Python versions MIT license

discomposer only builds messages. What a button or selection does (open a ticket, hand out a role) stays in your bot.

Install

pip install discomposer

Requires Python 3.11+ and discord.py 2.6+.

Fetch a template and send it

import discord
from discomposer import EditorClient, MediaStore, render_message, select_rows

editor = EditorClient(media=MediaStore("data/media"))

async def send(channel, code):
    design = await editor.fetch(code)  # validates and copies editor/Discord CDN images
    view = discord.ui.LayoutView(timeout=None)
    for item in render_message(
        design,
        guild=channel.guild,
        buttons={"ticket": lambda b: discord.ui.Button(label=b["label"], custom_id="mybot:ticket")},
        slots={"online": "12 members online"},
        selects=lambda menu, guild: select_rows(menu, f"mybot:{menu['id']}"),
    ):
        view.add_item(item)
    await channel.send(view=view, files=editor.media.files_for(design))

render_message returns the text outside the box (if any) and the filled container. Use render to fill a container you created yourself.

Offer your bot's features in the editor

from discomposer import guild_context

link = await editor.open({
    "title": "Ticket panel",
    "context": {
        **guild_context(guild),
        "buttons": [{"id": "ticket", "label": "Open ticket"}],
        "selects": [{"purpose": "ticket_categories", "label": "Ticket categories", "roles": "optional"}],
    },
    "design": {"blocks": [{"text": "## Support"}]},
})

The person designs the message at link and gives your bot the new code.

Handle a selection

Values and roles only ever come from the stored template, never from the interaction:

from discomposer import category_roles, chosen_category, ticket_overwrites

option = chosen_category(saved_design, "tickets", interaction.data["values"][0])
if option:
    roles = category_roles(guild, option)
    channel = await guild.create_text_channel(
        f"ticket-{interaction.user.name}",
        overwrites=ticket_overwrites(guild, interaction.user, roles),
    )

Use your own editor

editor = EditorClient(
    base_url="https://your-editor.example",
    media=MediaStore("data/media"),
)

Shared links supply a code; they never change the configured host. Your editor implements the same open HTTP protocol. The template format and bot library are independent of the closed-source hosted frontend. A reusable backend is available through the JS package's discomposer/server entry point; it serves both bot libraries.

API overview

Area Functions
Format validate, validate_design, find_select, selects_for, chosen_options
Sending render, render_message, outside_text, select_rows, fill_variables, VARIABLES
Editor EditorClient (open, fetch, fetch_document, upload, adopt_images, expose_attachments, open_message), guild_context, parse_code
Images MediaStore (save, files_for)
Tickets ticket_categories, chosen_category, category_roles, missing_roles, ticket_overwrites, transcript_markdown

Errors: TemplateError (format), EditorError (editor, network), MediaError (images). Messages are written for end users.

The template format is specified in spec/FORMAT.md. A JavaScript version for discord.js is available as discomposer on npm.

discomposer is not affiliated with or endorsed by Discord Inc.

Use one MediaStore instance per directory. Saves through that instance serialize quota checks and publish complete files through an atomic rename. Separate processes sharing a directory need coordination supplied by the application.

Image adoption copies editor uploads and Discord CDN images. Other HTTPS image URLs remain external references and depend on their host remaining available.

Metadata

Release files for discomposer 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for discomposer 0.2.0
File Size Uploaded Provenance Actions
discomposer-0.2.0.tar.gz 21.0 kB With provenance Details for discomposer-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for discomposer 0.2.0
File Interpreter ABI Platform Actions
discomposer-0.2.0-py3-none-any.whl Python 3 none any Details for discomposer-0.2.0-py3-none-any.whl

Total release size: 40.1 kB

Release files / discomposer-0.2.0.tar.gz

Download URL discomposer-0.2.0.tar.gz
Size 21.0 kB
Tags Source
SHA-256 checksum
How to use checksums
689a8a709584031feb6595c7a4915e77dbd2665ea380662660f74c04a6eb62ce
BLAKE2b-256 checksum
How to use checksums
54075ee9c9be36535f447eb70354aef97c4330cdd217ff38129a74d1fb6ec5e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.

Transparency log

Release files / discomposer-0.2.0-py3-none-any.whl

Download URL discomposer-0.2.0-py3-none-any.whl
Size 19.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c7f227b182305cf58702731fc1af939f067c08572ee66a47247d2d1a00a1d837
BLAKE2b-256 checksum
How to use checksums
08722e5981ab10e331c94cb5c77d1a447e298834021ff6db1fbd2ad65b34ac14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.

Transparency log

Security for discomposer 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for discomposer-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page