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
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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.