Domain Rich Cards & Display
Relevant source files
The following files were used as context for generating this wiki page:
Domain Rich Cards represent the primary user interface for displaying search results within the mdeai platform's AI-first discovery shell. These components are designed to provide a unified, "one listing surface" experience across various verticals such as cafes, restaurants, attractions, and rentals, ensuring that generative AI results are presented with consistent styling and functionality.
The system utilizes a "card unification" strategy where every rich card includes specific metadata such as a data-result-kind and a data-pin-id to synchronize with map displays and prevent duplicate listing surfaces.
Sources: e2e/rich-card-dedup.spec.ts:15-18, e2e/card-unification.spec.ts:16-20
Architecture and Component Hierarchy
The display system is built upon a modular architecture where high-level domain containers manage the layout and synchronization of specialized card components.
Domain Results Orchestration
The DomainResults component serves as the orchestrator for vertical-specific lists. It handles the mapping of raw tool output data into specific UI components like RestaurantCard or AttractionCard. It also integrates with ToolPinsSync to ensure that results shown in the chat are reflected as pins on the map.
The diagram above shows the relationship between the orchestration layer and specific domain cards.
Sources: src/components/copilot/domain-results.tsx:75-90, src/components/browse/tests/venue-card-shell.test.tsx:7-15
Card Unification and Shells
To maintain visual consistency, the system uses a VenueCardShell. This shell provides standard layout features including media areas, footers, and interactive states.
| Attribute | Purpose |
|---|---|
data-result-kind | Identifies the domain vertical (e.g., cafe, restaurant, rental). |
data-pin-id | Unique identifier for map synchronization. |
data-selected | Boolean string indicating the card is focused or hovered. |
composition | Supports different visual styles like legacy or nova. |
Sources: src/components/browse/tests/venue-card-shell.test.tsx:21-35, e2e/card-unification.spec.ts:25-30
Specialized Card Components
Attraction Card
The AttractionCard is used for landmarks and activities. It prioritizes information such as duration, best time of day, and category badges.
- Key Features: Image/Placeholder toggle, rating formatting, and dynamic deep-linking to Google Maps or internal directions.
- Data Structure: Includes
priceUsd,durationMinutes, andbestTimeOfDay.
Sources: src/components/copilot/attraction-card.tsx:13-25, src/components/copilot/attraction-card.tsx:90-110
Grounded Place Card (Cafes/Venues)
Grounded cards are specifically designed for results verified through Google Maps grounding. They emphasize "Google-verified" status and provide specific facts like price level and open status.
Sequence illustrating the data enrichment flow for grounded cards.
Sources: src/components/copilot/grounded-place-card.tsx:10-25, src/components/copilot/tests/grounded-place-card.test.tsx:7-15
Data Flow and Synchronization
Map Synchronization
Interaction with a card (hover or focus) triggers a selection state that is synchronized with the map. The DomainResults component uses scrollIntoView to ensure that when a pin is selected on the map, the corresponding rich card is brought into view in the chat panel.
Sources: src/components/copilot/domain-results.tsx:112-118
Result Deduplication and Sanitization
The system includes logic to prevent the AI model from leaking raw JSON payloads or repeating results in plain text that are already displayed as cards. The sanitizeAssistantChatContent function removes balanced JSON objects and specific "boilerplate" text associated with rental or grounding results.
// Example of identifying tool leaks that should be hidden from the UI
export function isToolLeakJson(value: unknown): boolean {
const o = value as Record<string, unknown>;
if (o.source === "grounding") return true;
if (Array.isArray(o.results) && o.results.some(r => "placeId" in r)) return true;
return false;
}
Sources: src/lib/sanitize-assistant-chat-content.ts:40-55, src/lib/sanitize-assistant-chat-content.ts:110-120
UI/UX Rules and Constraints
The display of rich cards follows strict "Critical Rules" defined in the platform's discovery registry to ensure accuracy and professionalism:
- No Invented Data: Cards must never show invented prices, URLs, or venues.
- Cardinality: Limit display to 5–10 cards per response to maintain readability.
- Deduplication: Results must be deduplicated by title, date, and venue before rendering.
- Mobile Responsiveness: Cards must maintain a target tap area of at least 44x44px and avoid horizontal overflow on mobile viewports (390px).
Sources: src/lib/events/trusted-event-sources.ts:60-68, e2e/screens/SCREEN-018-mobile-shell.spec.ts:100-105
Summary
The Domain Rich Cards & Display system provides a unified interface for Medellín discovery. By abstracting domain-specific data into consistent card structures (RestaurantCard, AttractionCard, RentalCard) and enforcing strict deduplication and map synchronization rules, the platform ensures that AI-generated suggestions are both visually professional and technically grounded in real-world data.