The four cards on the public /integrations landing page (Notion, Google Docs, Slack, Stripe) ship with default copy. Operators can override the name, category, tagline, and description of any card from /settings/system → Integrations → Integration card copy. The icon and accent colour stay controlled by the codebase so editing copy can't break the layout.

Where the override lives

Stored as JSON on app_settings.integration_cards. Resolved at render time by App\Support\IntegrationCardsContent::resolve() which overlays admin overrides on top of the hardcoded defaults in defaults(), keyed by card name (case-insensitive).

Per-field fallback semantics

Adding a new card

Not exposed in the admin UI by design — the card layout depends on a known icon + accent + integration kind. To add a card, edit IntegrationCardsContent::defaults() and rebuild. The admin form will then surface it as a new editable row.

Why icon + accent aren't editable

Both feed Tailwind colour tokens + lucide-react icon imports bundled by Vite. Letting the admin type an arbitrary icon name or hex code would either silently render an empty box or break the page when the build can't tree-shake the import. The trade- off is intentional: editable copy gives operators ownership of messaging without the foot-guns of layout / styling.