One message for four backends¶
In this tutorial you will build one rich message and render it for Slack, Discord, Symphony, and Telegram. No credentials or network connection are required.
Build the message¶
Chatom’s frontend consists of backend-independent models and formatting nodes. Build a status message with the fluent chatom.MessageBuilder:
def build_status_message():
"""Build a backend-independent status message."""
return (
MessageBuilder()
.heading("Deployment status", level=2)
.paragraph("The same message object is ready for every configured backend.")
.bold("Environment: ")
.text("production")
.line_break()
.bullet_list(["API: healthy", "Workers: healthy"])
.table(
[["API", "healthy"], ["Workers", "healthy"]],
headers=["Service", "State"],
)
.build()
)
The object contains structure, not platform markup. The heading, list, and table remain typed nodes until rendering.
Render for each backend¶
Render the same object with each backend name:
def main():
message = build_status_message()
for backend in ("slack", "discord", "symphony", "telegram"):
print(f"--- {backend} ---")
print(message.render_for(backend))
Run the complete example:
python -m chatom.examples.unified_frontend
Notice how the outputs differ:
Slack uses mrkdwn and a fixed-width table.
Discord uses Discord-flavored Markdown and a Markdown table.
Symphony uses MessageML elements.
Telegram uses its supported HTML subset and a preformatted table.
No conditional rendering logic appears in the application. chatom.FormattedMessage.render_for() selects the platform format at the boundary.
Send the rendered result¶
A connected backend accepts the same channel-and-content call shape:
channel = await backend.fetch_channel(name="operations")
content = message.render_for(backend.name)
await backend.send_message(channel, content)
Only backend construction and credentials vary. Message construction, channel lookup, and sending use the common frontend.