|
| 1 | +# Design: AI Catalog Frontend |
| 2 | + |
| 3 | +## Context |
| 4 | + |
| 5 | +Boost has a backend with 30+ API routes and 9 plugin packages but no frontend. The AI Catalog is the first frontend feature. The plugin architecture must support future domains (chat, admin, agent gallery) without restructuring. |
| 6 | + |
| 7 | +## Goals |
| 8 | + |
| 9 | +- NFS-only frontend plugin using Backstage Blueprints |
| 10 | +- Browse page for marketplace-style AI asset discovery |
| 11 | +- Entity page extensions for asset details and adoption actions |
| 12 | +- Dev app shell for local development |
| 13 | +- BUI component library for new UI components |
| 14 | + |
| 15 | +## Non-Goals |
| 16 | + |
| 17 | +- Chat UI, admin panels, or agent gallery (future domains) |
| 18 | +- Custom entity detail pages (use existing catalog pages) |
| 19 | +- RHDH dynamic plugin packaging (Scalprum/export-dynamic deferred) |
| 20 | +- Custom search collator for global search (rely on default catalog indexing) |
| 21 | + |
| 22 | +## Decisions |
| 23 | + |
| 24 | +### Decision 1: NFS-only plugin, no legacy entry point |
| 25 | + |
| 26 | +This is a new plugin with no existing consumers. The default export from `src/index.ts` is `createFrontendPlugin`. No `src/alpha.tsx`, no `createPlugin` from `@backstage/core-plugin-api`. |
| 27 | + |
| 28 | +### Decision 2: Standalone browse page + entity extensions |
| 29 | + |
| 30 | +Two surface types: |
| 31 | + |
| 32 | +- `PageBlueprint` at `/ai-catalog` for the card grid browse view. The existing catalog table at `/catalog` does not support card layout, category grouping, or inline adoption actions — a dedicated page is needed. |
| 33 | +- `EntityCardBlueprint` and `EntityContentBlueprint` on existing catalog entity pages for AI-specific cards and tabs. No custom detail page. |
| 34 | + |
| 35 | +### Decision 3: catalogApiRef for data, BoostApiClient for download proxy only |
| 36 | + |
| 37 | +The browse page queries AI assets through the standard `catalogApiRef` — no custom boost backend routes for browsing. The only custom backend interaction is the download proxy route for git-hosted asset ZIP downloads. |
| 38 | + |
| 39 | +### Decision 4: Single isAiAsset filter, components handle kind differences |
| 40 | + |
| 41 | +One `isAiAsset(entity)` condition filter for all entity page Blueprints. The filter checks entity kind and `spec.type` against the AI asset entity model (see below). Individual components handle kind-specific rendering differences internally — e.g., the download card checks `spec.location.type` and renders nothing when absent. |
| 42 | + |
| 43 | +### Decision 5: Client-side pagination |
| 44 | + |
| 45 | +`catalogApi.getEntities()` returns the full matching dataset. Client-side pagination is sufficient for the Dev Preview target of ~500 assets. If catalogs grow beyond this, the hook internals can switch to `queryEntities` (cursor-based) without changing components. |
| 46 | + |
| 47 | +### Decision 6: BUI for UI components, PatternFly chatbot for future chat |
| 48 | + |
| 49 | +BUI (`@backstage/ui`) is the component library for all new UI. MUI v5 as fallback where BUI lacks coverage. PatternFly AI chatbot (`@patternfly/chatbot`) is reserved for the future chat domain to maintain consistency with Lightspeed. |
| 50 | + |
| 51 | +### Decision 7: RBAC graceful degradation |
| 52 | + |
| 53 | +Permission checks for `ai-catalog.asset.read.usage-docs` default to allow when the permission is not yet registered (RHDHPLAN-1508 not built). Content is shown, and enforcement activates automatically when RBAC lands. |
| 54 | + |
| 55 | +## Entity Model |
| 56 | + |
| 57 | +Backstage v1.51.0 introduced `AiResource` kind and `API` with `spec.type: mcp-server` via `@backstage/plugin-catalog-backend-module-ai-model`. Boost uses upstream kinds where available: |
| 58 | + |
| 59 | +| Category | Entity Kind | spec.type | Notes | |
| 60 | +|---|---|---|---| |
| 61 | +| Skills | AiResource | skill | Upstream. disciplines, categories, agents, dependsOn | |
| 62 | +| Rules | AiResource | rule | Upstream. category (required), rationale (required) | |
| 63 | +| MCP Servers | API | mcp-server | Upstream. spec.remotes list | |
| 64 | +| Agents | Component | ai-agent | Boost-defined | |
| 65 | +| Models | Resource | ai-model | Boost-defined. RFC #33060 pending | |
| 66 | +| Tools | Resource | ai-tool | Boost-defined (Kagenti) | |
| 67 | +| Vector Stores | Resource | vector-store | Boost-defined | |
| 68 | + |
| 69 | +## Components |
| 70 | + |
| 71 | +### AiCatalogPage |
| 72 | +Browse page with card grid, search, and filters. PluginHeader provided by the framework. |
| 73 | +- Card grid grouped by category with responsive layout |
| 74 | +- Debounced keyword search (300ms) |
| 75 | +- Filter controls: category, lifecycle, tags, owner, source connector (AND logic) |
| 76 | +- Filter/search state in URL query params |
| 77 | +- Pagination, sort (name, last updated) |
| 78 | +- Loading skeletons, empty state with clear-filters, error state with retry |
| 79 | + |
| 80 | +### AiAssetCard |
| 81 | +Card displaying key metadata for one AI asset. Used in the browse grid. |
| 82 | +- Name, truncated description, category icon/badge, lifecycle badge |
| 83 | +- Tags, owner, version, source connector indicator |
| 84 | +- Click navigates to catalog entity detail page |
| 85 | + |
| 86 | +### AiAssetSummaryCard |
| 87 | +EntityCardBlueprint on entity overview. Shows AI-specific metadata. |
| 88 | +- Category badge, current/recommended version, source attribution, lifecycle |
| 89 | + |
| 90 | +### DownloadAdoptCard |
| 91 | +EntityCardBlueprint on entity overview. Conditional on spec.location.type. |
| 92 | +- git: Download button triggers ZIP download via backend proxy |
| 93 | +- oci: docker/podman toggle with copyable pull command |
| 94 | +- Absent: card not rendered |
| 95 | + |
| 96 | +### VersionListCard |
| 97 | +EntityCardBlueprint on entity overview. Shows all versions of the asset. |
| 98 | +- Current/recommended highlighted |
| 99 | +- Click navigates to that version's entity page |
| 100 | + |
| 101 | +### UsageTab |
| 102 | +EntityContentBlueprint tab. RBAC-gated usage documentation. |
| 103 | +- With usage-docs permission: TechDocs content or external links |
| 104 | +- Without permission: "Contact owner for access" affordance |
| 105 | + |
| 106 | +## Design Reference |
| 107 | + |
| 108 | +UX prototype: https://agentic-524bde.pages.redhat.com/skill-marketplace/overview (VPN required) |
| 109 | + |
| 110 | +## Acceptance Criteria |
| 111 | + |
| 112 | +### AiCatalogPage |
| 113 | +- Developer sees card grid grouped by category at /ai-catalog |
| 114 | +- Search filters cards within 300ms |
| 115 | +- Multiple filters narrow results with AND logic |
| 116 | +- Filter state in URL survives refresh and is shareable |
| 117 | +- Empty state when no match; error state when catalog unreachable |
| 118 | +- Keyboard navigable through all interactive elements |
| 119 | + |
| 120 | +### AiAssetCard |
| 121 | +- Card displays all metadata fields from entity |
| 122 | +- Click navigates to catalog entity detail page |
| 123 | + |
| 124 | +### AiAssetSummaryCard |
| 125 | +- Renders on AI asset entity pages only |
| 126 | +- Shows category, version, source, lifecycle |
| 127 | + |
| 128 | +### DownloadAdoptCard |
| 129 | +- Download button on git assets triggers ZIP download |
| 130 | +- Docker/podman toggle on OCI assets with copyable pull command |
| 131 | +- Not rendered when spec.location.type absent |
| 132 | + |
| 133 | +### VersionListCard |
| 134 | +- Shows all versions; current highlighted |
| 135 | +- Click navigates to version's entity page |
| 136 | + |
| 137 | +### UsageTab |
| 138 | +- Renders TechDocs when annotation present; external links as fallback |
| 139 | +- Shows "Contact owner" when user lacks usage-docs permission |
| 140 | +- Tab only appears on AI asset entities |
0 commit comments