Skip to content

Commit 90021e7

Browse files
committed
refactor(landing): bake integration landing content into generated json via docs-gen
Moves landing content (install walkthrough + privacy) out of a render-time augment and into the generation pipeline: generate-docs reads the pure-data content map and writes landingContent into integrations.json, so the page reads a single source (integration.landingContent). Canonical types live in integrations/data/types.ts.
1 parent 3707d45 commit 90021e7

5 files changed

Lines changed: 76 additions & 30 deletions

File tree

apps/sim/app/(landing)/integrations/(shell)/[slug]/page.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { TemplateCardButton } from '@/app/(landing)/integrations/(shell)/[slug]/
99
import { IntegrationIcon } from '@/app/(landing)/integrations/components/integration-icon'
1010
import { blockTypeToIconMap } from '@/app/(landing)/integrations/data/icon-mapping'
1111
import integrations from '@/app/(landing)/integrations/data/integrations.json'
12-
import { INTEGRATION_LANDING_CONTENT } from '@/app/(landing)/integrations/data/landing-content'
1312
import type { AuthType, FAQItem, Integration } from '@/app/(landing)/integrations/data/types'
1413
import { TEMPLATES } from '@/app/workspace/[workspaceId]/home/components/template-prompts/consts'
1514

@@ -218,7 +217,7 @@ export default async function IntegrationPage({ params }: { params: Promise<{ sl
218217
const { name, description, longDescription, bgColor, docsUrl, operations, triggers, authType } =
219218
integration
220219

221-
const landingContent = INTEGRATION_LANDING_CONTENT[slug]
220+
const landingContent = integration.landingContent
222221

223222
const IconComponent = blockTypeToIconMap[integration.type]
224223
const faqs = buildFAQs(integration)

apps/sim/app/(landing)/integrations/data/integrations.json

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13306,7 +13306,35 @@
1330613306
"authType": "oauth",
1330713307
"category": "tools",
1330813308
"integrationTypes": ["communication", "developer-tools"],
13309-
"tags": ["messaging", "webhooks", "automation"]
13309+
"tags": ["messaging", "webhooks", "automation"],
13310+
"landingContent": {
13311+
"install": {
13312+
"heading": "Add Sim to your Slack workspace",
13313+
"intro": "Sim connects to Slack through Slack’s official OAuth flow. The “Add to Slack” button lives inside your Sim account (after sign-in) — connect from there and the Sim bot is installed in your Slack workspace. The steps below show exactly how to reach it.",
13314+
"steps": [
13315+
{
13316+
"title": "Create your free Sim account",
13317+
"body": "Sign up at sim.ai — no credit card required."
13318+
},
13319+
{
13320+
"title": "Add a Slack block",
13321+
"body": "Open a workflow, drag in a Slack block, and open its credential dropdown."
13322+
},
13323+
{
13324+
"title": "Connect Slack",
13325+
"body": "Click Connect Slack, choose your workspace, and approve the requested permissions. This installs the Sim bot in your Slack workspace."
13326+
},
13327+
{
13328+
"title": "Invite the bot and build",
13329+
"body": "Invite the Sim bot to the channels it should act in, pick a Slack action, wire it into your agent, and run."
13330+
}
13331+
]
13332+
},
13333+
"privacy": {
13334+
"body": "Sim requests only the Slack permissions its actions and triggers need, and never shows private channel names or messages to people who are not members of those channels in Slack.",
13335+
"href": "/privacy"
13336+
}
13337+
}
1331013338
},
1331113339
{
1331213340
"type": "smtp",

apps/sim/app/(landing)/integrations/data/landing-content.ts

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,12 @@
11
/**
2-
* Hand-authored, integration-specific landing content that augments the
3-
* generated `integrations.json`. Kept in a separate module so it survives
4-
* regeneration by `scripts/generate-docs.ts`. Keyed by integration slug;
5-
* the integration detail page renders these sections only when present.
2+
* Hand-authored, integration-specific landing content, keyed by integration
3+
* slug. This is a pure-data generation input: `scripts/generate-docs.ts` reads
4+
* it and bakes the matching entry into `integrations.json`, so the landing page
5+
* consumes a single source (`integration.landingContent`) with no render-time
6+
* augmentation. Has no app imports so the build script can import it safely.
67
*/
78

8-
export interface IntegrationInstallStep {
9-
title: string
10-
body: string
11-
}
12-
13-
export interface IntegrationLandingContent {
14-
/**
15-
* Install walkthrough for OAuth apps whose connection lives behind sign-in.
16-
* Provides the "Add to {app}" instructions that app marketplaces require
17-
* when the install button sits behind a login.
18-
*/
19-
install?: {
20-
heading: string
21-
intro: string
22-
steps: IntegrationInstallStep[]
23-
}
24-
/** Short data-handling summary shown next to a privacy-policy link. */
25-
privacy?: {
26-
body: string
27-
href: string
28-
}
29-
}
9+
import type { IntegrationLandingContent } from '@/app/(landing)/integrations/data/types'
3010

3111
export const INTEGRATION_LANDING_CONTENT: Record<string, IntegrationLandingContent> = {
3212
slack: {

apps/sim/app/(landing)/integrations/data/types.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,29 @@ export interface FAQItem {
1919
answer: string
2020
}
2121

22+
export interface IntegrationInstallStep {
23+
title: string
24+
body: string
25+
}
26+
27+
export interface IntegrationLandingContent {
28+
/**
29+
* Install walkthrough for OAuth apps whose connection lives behind sign-in.
30+
* Provides the "Add to {app}" instructions that app marketplaces require
31+
* when the install button sits behind a login.
32+
*/
33+
install?: {
34+
heading: string
35+
intro: string
36+
steps: IntegrationInstallStep[]
37+
}
38+
/** Short data-handling summary shown next to a privacy-policy link. */
39+
privacy?: {
40+
body: string
41+
href: string
42+
}
43+
}
44+
2245
export interface Integration {
2346
type: string
2447
slug: string
@@ -36,4 +59,5 @@ export interface Integration {
3659
category: string
3760
integrationTypes?: string[]
3861
tags?: string[]
62+
landingContent?: IntegrationLandingContent
3963
}

scripts/generate-docs.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env ts-node
22
import fs from 'fs'
33
import path from 'path'
4-
import { fileURLToPath } from 'url'
4+
import { fileURLToPath, pathToFileURL } from 'url'
55
import { glob } from 'glob'
66

77
console.log('Starting documentation generator...')
@@ -183,6 +183,7 @@ interface IntegrationEntry {
183183
category: string
184184
integrationTypes?: string[]
185185
tags?: string[]
186+
landingContent?: Record<string, unknown>
186187
}
187188

188189
/**
@@ -665,6 +666,19 @@ async function writeIntegrationsJson(iconMapping: Record<string, string>): Promi
665666

666667
const triggerRegistry = await buildTriggerRegistry()
667668
const { desc: toolDescMap, name: toolNameMap } = await buildToolDescriptionMap()
669+
670+
// Hand-authored, integration-specific landing content (install walkthrough,
671+
// privacy blurb), keyed by slug. Imported as pure data — its only import is
672+
// type-only and erased at runtime — and baked into the entries below so the
673+
// landing page reads a single source instead of augmenting at render time.
674+
const landingContentModule = await import(
675+
pathToFileURL(path.join(LANDING_INTEGRATIONS_DATA_PATH, 'landing-content.ts')).href
676+
)
677+
const landingContentMap = (landingContentModule.INTEGRATION_LANDING_CONTENT ?? {}) as Record<
678+
string,
679+
Record<string, unknown>
680+
>
681+
668682
const integrations: IntegrationEntry[] = []
669683
const seenBaseTypes = new Set<string>()
670684
const blockFiles = (await glob(`${BLOCKS_PATH}/*.ts`)).sort()
@@ -778,6 +792,7 @@ async function writeIntegrationsJson(iconMapping: Record<string, string>): Promi
778792
}
779793
: {}),
780794
...(config.tags ? { tags: config.tags } : {}),
795+
...(landingContentMap[slug] ? { landingContent: landingContentMap[slug] } : {}),
781796
})
782797
}
783798
}

0 commit comments

Comments
 (0)