#Cards
Cards are interactive rich messages. Each platform adapter converts the SDK's abstract card model into its native format (Block Kit, Inline Keyboard, Embed, etc.).
#Creating a Card
use BootDesk\ChatSDK\Core\Cards\Card;
use BootDesk\ChatSDK\Core\Cards\Button;
$card = Card::make()
->header('Special Offer')
->section(fn ($s) => $s->text('50% off today only!'))
->image('https://example.com/banner.jpg')
->actions([
Button::primary('Shop Now', 'action_shop'),
Button::secondary('Dismiss', 'action_dismiss'),
]);
#Card Elements
#Header
$card->header('Title');
#Sections
$card->section(function (Section $s) {
$s->text('Description text');
$s->field('Key', 'Value');
});
#Text
$card->text('Plain text');
$card->text('**Bold text**', TextStyle::Markdown);
#Images
$card->image('https://example.com/photo.jpg', 'Alt text');
#Tables
$card->table(
headers: ['Name', 'Status'],
rows: [
['Alice', '✅'],
['Bob', '❌'],
],
);
Slack limits: Native tables support up to 100 rows and 20 columns. Beyond that, the adapter falls back to an ASCII-rendered table in a code block (subject to Slack's 3000 char mrkdwn limit). Only one native table per message — subsequent tables render as ASCII.
#Buttons
$card->actions([
Button::primary('Label', 'action_id'),
Button::secondary('Label', 'action_id'),
Button::danger('Delete', 'action_delete'),
]);
Button::link('Website', 'https://example.com');
#Dividers
$card->divider();
#Sending a Card
$thread->post(PostableMessage::card($card));
#Button Action Href
Buttons can include a fallback URL for platforms that don't support native buttons:
Button::primary('View', 'action_view', actionHref: 'https://example.com');
Button::link('Open', 'https://example.com');
When actionHref is set and the adapter renders as plain text (e.g., GitHub, Linear), it renders as a markdown link. Otherwise, the platform's native button format is used.
#Location Attachments
For platform-agnostic location parsing (Telegram, WhatsApp, Messenger, Instagram), use Attachment::location():
$attachment = Attachment::location(
lat: -23.5505,
lng: -46.6333,
name: 'São Paulo',
address: 'São Paulo, Brazil',
);
$attachment->type; // 'location'
$attachment->lat; // -23.5505
$attachment->lng; // -46.6333
$attachment->address; // 'São Paulo, Brazil'
$attachment->isDataUrl(); // true (GeoJSON data URL)
The web adapter's WebLocationCard renders the location client-side. For outgoing location on platforms without native location types (Slack, Discord, Twilio, Messenger, Instagram), the SDK falls back to a Google Maps link in message text.