From 5ca3b7eedd1cc7c54ee5de67c11f8c87a68b2ee3 Mon Sep 17 00:00:00 2001 From: Lindsey Zylstra Date: Fri, 19 Dec 2025 17:04:51 -0800 Subject: [PATCH 1/4] Add docs and resources section to integration pages --- .../pages/integrations/[integration].vue | 150 ++++++++++++++++++ .../api/integrations/[integration].get.ts | 41 ++++- types/marketplace.ts | 8 + .../integration-external-resource.ts | 14 ++ 4 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 types/schema/marketplace/integration-external-resource.ts diff --git a/layers/marketplace/pages/integrations/[integration].vue b/layers/marketplace/pages/integrations/[integration].vue index 73144c9a..5fc5145b 100644 --- a/layers/marketplace/pages/integrations/[integration].vue +++ b/layers/marketplace/pages/integrations/[integration].vue @@ -79,6 +79,38 @@ useSchemaOrg([ /> + +
+ + +
+
@@ -317,6 +349,124 @@ useSchemaOrg([ margin-block-start: var(--space-6); } +.external-resources-list { + display: flex; + flex-direction: column; + gap: var(--space-4); + margin-block-start: var(--space-6); +} + +.external-resource-card { + display: flex; + align-items: center; + gap: var(--space-4); + padding: var(--space-4); + border-radius: var(--rounded-lg); + border: 1px solid var(--gray-200); + background-color: var(--background); + color: var(--foreground); + text-decoration: none; + transition: all var(--duration-200) var(--ease-out); + position: relative; + + &:hover { + border-color: var(--gray-300); + box-shadow: 0 4px 12px rgb(0 0 0 / 10%); + transform: translateY(-2px); + + .resource-title { + color: var(--primary); + } + + .external-link-icon { + color: var(--primary); + } + } + + &:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px var(--primary-100); + } + + &:focus-visible { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px var(--primary-100); + } +} + +.resource-image { + flex-shrink: 0; + width: 120px; + height: 120px; + border-radius: var(--rounded-md); + overflow: hidden; + background-color: var(--gray-100); + display: flex; + align-items: center; + justify-content: center; + + @media (width <= 30rem) { + display: none; + } + + img { + width: 100%; + height: 100%; + object-fit: cover; + } +} + +.resource-image-placeholder { + flex-shrink: 0; + width: 120px; + height: 120px; + border-radius: var(--rounded-md); + background-color: var(--gray-100); + display: flex; + align-items: center; + justify-content: center; + color: var(--gray-400); + + @media (width <= 30rem) { + display: none; + } +} + +.resource-content { + flex: 1; + display: flex; + flex-direction: column; + gap: var(--space-2); + min-width: 0; +} + +.resource-title { + font-size: var(--font-size-lg); + font-weight: 600; + line-height: var(--line-height-lg); + margin: 0; + color: var(--foreground); + transition: color var(--duration-200) var(--ease-out); +} + +.resource-description { + color: var(--gray-600); + font-size: var(--font-size-sm); + line-height: var(--line-height-sm); + margin: 0; +} + +.external-link-icon { + position: absolute; + top: var(--space-4); + right: var(--space-4); + flex-shrink: 0; + color: var(--gray-400); + transition: color var(--duration-200) var(--ease-out); +} + .desktop-only { display: none; diff --git a/layers/marketplace/server/api/integrations/[integration].get.ts b/layers/marketplace/server/api/integrations/[integration].get.ts index 4efbfc46..18f122c2 100644 --- a/layers/marketplace/server/api/integrations/[integration].get.ts +++ b/layers/marketplace/server/api/integrations/[integration].get.ts @@ -1,10 +1,13 @@ import type { MarketplaceIntegration, MarketplaceExtension } from '~/types/marketplace'; +import type { IntegrationExternalResource } from '~/types/schema/marketplace/integration-external-resource'; import { arrayToString } from '~/utils/arrayToString'; +import { isUuid } from '~/layers/marketplace/server/utils/isUuid'; import { typesenseServer } from '~/layers/marketplace/server/services/typesense'; import { consola } from 'consola'; interface IntegrationWithExtensions extends MarketplaceIntegration { extensionDetails?: MarketplaceExtension[]; + external_resources?: IntegrationExternalResource[]; } const config = useRuntimeConfig(); @@ -27,14 +30,38 @@ export default defineEventHandler( const response = await $fetch<{ data?: MarketplaceIntegration[] } | MarketplaceIntegration[]>( `${directusUrl}/items/integrations`, { - params: { - fields: ['*'], - filter, + query: { + fields: [ + '*', + 'external_resources.id', + 'external_resources.title', + 'external_resources.url', + 'external_resources.description', + 'external_resources.image', + 'external_resources.sort', + 'external_resources.status', + ], + filter: { + ...filter, + status: { + _eq: 'published', + }, + }, + deep: { + external_resources: { + _filter: { + status: { + _eq: 'published', + }, + }, + _sort: ['sort'], + }, + }, }, }, ); - const integration = Array.isArray(response) ? response[0] : (response as any)?.data[0] || []; + const integration = Array.isArray(response) ? response[0] : (response as any)?.data?.[0] || null; if (!integration) { throw createError({ @@ -66,9 +93,15 @@ export default defineEventHandler( } } + const externalResources: IntegrationExternalResource[] = + integration.external_resources && Array.isArray(integration.external_resources) + ? integration.external_resources + : []; + return { ...integration, extensionDetails, + external_resources: externalResources, }; } catch (error) { consola.error('Integration detail API error:', error); diff --git a/types/marketplace.ts b/types/marketplace.ts index 2bedc2d7..ad7942d9 100644 --- a/types/marketplace.ts +++ b/types/marketplace.ts @@ -155,6 +155,14 @@ export interface MarketplaceIntegration { }>; content: string; extensionDetails?: MarketplaceExtension[]; + external_resources?: Array<{ + id: string; + title: string; + url: string; + description?: string | null; + image?: File | string | null; + sort?: number | null; + }>; } export interface MarketplaceRequest { diff --git a/types/schema/marketplace/integration-external-resource.ts b/types/schema/marketplace/integration-external-resource.ts new file mode 100644 index 00000000..33f8c2ba --- /dev/null +++ b/types/schema/marketplace/integration-external-resource.ts @@ -0,0 +1,14 @@ +import type { File } from '../system'; + +export interface IntegrationExternalResource { + /** @required */ + id: string; + sort?: number | null; + /** @required */ + title: string; + /** @required */ + url: string; + description?: string | null; + image?: File | string | null; + integration?: string | null; +} From 28939f42683eca214ab71d0e5e74a255ec3c466c Mon Sep 17 00:00:00 2001 From: Bryant Gillespie Date: Wed, 7 Jan 2026 08:23:32 -0500 Subject: [PATCH 2/4] Update layers/marketplace/pages/integrations/[integration].vue Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- layers/marketplace/pages/integrations/[integration].vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layers/marketplace/pages/integrations/[integration].vue b/layers/marketplace/pages/integrations/[integration].vue index 5fc5145b..0639a19d 100644 --- a/layers/marketplace/pages/integrations/[integration].vue +++ b/layers/marketplace/pages/integrations/[integration].vue @@ -95,7 +95,7 @@ useSchemaOrg([ From 06afd190480edce9904c3fc0382ece45e6bc8f2a Mon Sep 17 00:00:00 2001 From: bryantgillespie Date: Wed, 7 Jan 2026 08:32:02 -0500 Subject: [PATCH 3/4] add status --- types/marketplace.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/types/marketplace.ts b/types/marketplace.ts index ad7942d9..f9afa42b 100644 --- a/types/marketplace.ts +++ b/types/marketplace.ts @@ -162,6 +162,7 @@ export interface MarketplaceIntegration { description?: string | null; image?: File | string | null; sort?: number | null; + status?: string | null; }>; } From 9c2626d06c95f78d124f3839b9e4d7869194ef02 Mon Sep 17 00:00:00 2001 From: bryantgillespie Date: Wed, 7 Jan 2026 08:35:47 -0500 Subject: [PATCH 4/4] copilot stinks --- layers/marketplace/pages/integrations/[integration].vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layers/marketplace/pages/integrations/[integration].vue b/layers/marketplace/pages/integrations/[integration].vue index 0639a19d..cd3b3749 100644 --- a/layers/marketplace/pages/integrations/[integration].vue +++ b/layers/marketplace/pages/integrations/[integration].vue @@ -95,7 +95,7 @@ useSchemaOrg([