From bfb5366e983c254d6b30d19b39336de65a6d5f3d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Dec 2025 19:08:30 +0000 Subject: [PATCH 01/22] Add Fenestra Specification v0.1.0-draft Fenestra is a specification for describing platform UI component ecosystems, designed for submission to the OpenAPI Initiative (OAI). This draft includes: - Core specification schema (fenestra-spec.yaml) - README with overview and integration points - Example documents for HubSpot and Miro platforms - Known issues and roadmap (ISSUES.md) Key features: - Component catalogs with SDK bindings - Requirement levels (required/recommended/optional) - Custom component policies and publishing constraints - Web standard mappings (HTML elements, ARIA roles) - Extension points for platform UI injection Integrations addressed: - MCP Apps (Model Context Protocol UI) - JSON Forms (schema-driven rendering) - Arazzo (workflow orchestration) Known gaps documented for v0.2: - Declarative/JSON UI patterns (Slack Block Kit, etc.) - Mobile SDK ecosystems - Internationalization/localization - Compliance requirements (WCAG, SOC2, GDPR) - AI agent interaction mechanisms --- specs/fenestra/ISSUES.md | 225 +++++ specs/fenestra/README.md | 221 +++++ specs/fenestra/examples/hubspot.fenestra.yaml | 352 +++++++ specs/fenestra/examples/miro.fenestra.yaml | 276 ++++++ specs/fenestra/fenestra-spec.yaml | 922 ++++++++++++++++++ 5 files changed, 1996 insertions(+) create mode 100644 specs/fenestra/ISSUES.md create mode 100644 specs/fenestra/README.md create mode 100644 specs/fenestra/examples/hubspot.fenestra.yaml create mode 100644 specs/fenestra/examples/miro.fenestra.yaml create mode 100644 specs/fenestra/fenestra-spec.yaml diff --git a/specs/fenestra/ISSUES.md b/specs/fenestra/ISSUES.md new file mode 100644 index 0000000..497a372 --- /dev/null +++ b/specs/fenestra/ISSUES.md @@ -0,0 +1,225 @@ +# Fenestra Specification - Known Issues & Roadmap + +This document captures findings from adversarial review of the v0.1.0-draft specification. + +## Summary of Findings + +| Category | Critical | High | Medium | Low | +|----------|----------|------|--------|-----| +| Platform Ecosystem | 3 | 4 | 3 | 3 | +| MCP/JSON Forms Integration | 9 | 7 | 4 | 0 | +| Policy Edge Cases | 6 | 6 | 6 | 2 | +| Web Standards Mapping | 5 | 4 | 4 | 3 | + +--- + +## Critical Issues (Must Fix for v0.2) + +### 1. Declarative/JSON UI Patterns Not Supported + +**Problem**: Cannot describe platforms using JSON-based UI (Slack Block Kit, Discord, Microsoft Adaptive Cards). + +**Platforms affected**: Slack, Discord, Microsoft Teams, Zoom Apps + +**Required addition**: +```yaml +ComponentDefinitionStyle: + enum: + - sdkImport # Current: import { Button } from '@sdk' + - jsonPayload # NEW: {"type": "button", "text": "..."} + - htmlTemplate # NEW: + - dsl # NEW: Custom domain-specific language +``` + +### 2. Mobile SDK Ecosystems Completely Missing + +**Problem**: No support for iOS/Android native platforms. + +**Required additions**: +- Package managers: CocoaPods, Swift Package Manager, Android AAR, Flutter +- Platform field on SDK: web, ios, android, desktop, cli +- Language field: swift, kotlin, dart + +### 3. No Internationalization/Localization Support + +**Problem**: Zero support for RTL layouts, translations, or locale-specific components. + +**Required addition**: `I18nSupport` schema with locales, RTL, and translation keys. + +### 4. MCP Apps Integration Superficial + +**Problem**: `MCPAppsIntegration` lacks: +- UI Resource schema (how to declare UI in server manifests) +- Template definitions (form structure, layout, validation) +- Tool-to-UI bindings (connecting tools to UI surfaces) +- User consent mechanism for UI-initiated tool calls +- Bidirectional JSON-RPC communication details + +### 5. JSON Forms Integration Incomplete + +**Problem**: `JSONFormsIntegration` lacks: +- UI Schema structure (layouts, rules, options) +- Custom renderer specification (tester functions, ranking) +- Array control support (add/remove/reorder) +- Validation and error display patterns +- Categorization support (tabs, accordions, wizards) + +### 6. AI Agent Interaction Not Addressed + +**Problem**: Spec mentions AI agents but provides zero mechanisms for: +- UI capability discovery by agents +- Dynamic UI rendering from conversation context +- User response handling and tool parameter collection + +### 7. Arazzo Integration Missing + +**Problem**: Spec mentions Arazzo but has no schema for: +- Workflow step to UI binding +- Form submission as workflow input +- UI feedback on workflow progress + +### 8. Compliance Requirements Missing + +**Problem**: No way to express: +- Accessibility standards (WCAG AA/AAA, Section 508) +- Security certifications (SOC2, HIPAA, PCI-DSS, FedRAMP) +- Privacy regulations (GDPR, CCPA, COPPA) +- Data residency requirements + +### 9. ARIA Coverage Insufficient + +**Problem**: Single `ariaRole` field cannot express: +- ARIA states and properties (49 attributes) +- Composite patterns (combobox, tree, menu) +- Live region announcements +- APG pattern references + +--- + +## High Priority Issues (v0.2 or v0.3) + +### 10. Theming System Underdeveloped + +**Problem**: Only `designTokensProvided: boolean`, no: +- Dark/light mode specification +- Theme token schema (colors, spacing, typography) +- CSS custom properties integration + +### 11. Heavy React Bias + +**Problem**: Spec assumes React. Missing support for: +- Vue/Angular/Svelte/Solid +- CSS-only libraries (Mirotone) +- No-code/low-code builders +- Framework-agnostic patterns + +### 12. Hybrid Component Requirements + +**Problem**: Binary required/optional doesn't capture: +- Per-category requirements (SDK for forms, custom for charts) +- Per-extension-point requirements +- Feature-tier requirements + +### 13. Publishing Tier Complexity + +**Problem**: Only private/public/marketplace tiers. Missing: +- Beta/early access programs +- Partner tier hierarchies +- Regional/geographic policies +- Industry-specific tiers + +### 14. Review Workflow Complexity + +**Problem**: Simple boolean flags can't express: +- Multi-stage review pipelines +- Parallel vs sequential reviews +- Conditional review requirements +- Component-level vs app-level review + +### 15. CSS Layout Patterns Missing + +**Problem**: No CSS layout information: +- Flexbox/Grid assumptions +- Responsive breakpoints +- Container query support +- Design token exposure + +### 16. Form Semantics Missing + +**Problem**: No form participation semantics: +- HTML5 constraint validation API +- FormData integration +- Autocomplete/autofill support + +--- + +## Medium Priority Issues (v0.3+) + +### 17. Versioning and Deprecation Tracking + +**Problem**: Simple `deprecated: boolean` and `since: string`. Need: +- Sunset dates +- Migration guides +- Breaking change documentation +- Version compatibility matrix + +### 18. Browser Extension Patterns + +**Problem**: Missing extension point types: +- popup, sidepanel, devtools, contentScript + +### 19. Event Model Underdeveloped + +**Problem**: Simple event schema lacks: +- DOM event equivalents +- Event bubbling/composition +- Touch/gesture events +- Keyboard event expectations + +### 20. Custom Component Nuances + +**Problem**: Binary allowed/not-allowed. Need: +- Wrapper requirements +- Use-case-specific allowances +- Approved third-party library lists + +### 21. Time-Based Policies + +**Problem**: No time dimension: +- Deprecation timelines +- Migration windows +- Feature flag lifecycles +- Policy version transitions + +--- + +## Roadmap + +### v0.2.0 - Core Completeness +- [ ] Add `ComponentDefinitionStyle` for JSON/declarative UI +- [ ] Add `I18nSupport` schema +- [ ] Expand `MCPAppsIntegration` with resource/template/binding schemas +- [ ] Expand `JSONFormsIntegration` with UI schema/validation/renderers +- [ ] Add `ArazzoIntegration` schema +- [ ] Add `ComplianceRequirements` schema +- [ ] Expand ARIA to include states, properties, and composite patterns + +### v0.3.0 - Policy Maturity +- [ ] Add granular `ComponentRequirementPolicy` (per-category, per-extension-point) +- [ ] Expand `CustomComponentPolicy` with approved libraries, wrapper requirements +- [ ] Add `ReviewWorkflow` schema with multi-stage, conditional logic +- [ ] Add `PublishingTier` hierarchy (beta, partner levels, regional) +- [ ] Add `LifecyclePolicy` for time-based policies + +### v0.4.0 - Web Standards Depth +- [ ] Expand `WebStandardMapping` with multi-element structures +- [ ] Add `CSSLayoutPattern` schema +- [ ] Add `FormSemantics` schema +- [ ] Expand event model with DOM equivalents +- [ ] Add mobile platform equivalents + +### v1.0.0 - Production Ready +- [ ] Full cross-platform support (web, iOS, Android, desktop) +- [ ] AI agent interaction mechanisms +- [ ] Tooling for validation and code generation +- [ ] Reference implementations for major platforms diff --git a/specs/fenestra/README.md b/specs/fenestra/README.md new file mode 100644 index 0000000..3220e0b --- /dev/null +++ b/specs/fenestra/README.md @@ -0,0 +1,221 @@ +# Fenestra Specification + +> *Fenestra* (Latin for "window") - A specification for describing platform UI component ecosystems + +**Version**: 0.1.0-draft +**Status**: Early draft, seeking community feedback +**Target Foundation**: [OpenAPI Initiative (OAI)](https://www.openapis.org/), a Linux Foundation Collaborative Project + +--- + +## Overview + +Fenestra is a specification for describing how platforms expose UI component ecosystems to developers building integrations, apps, and extensions. It provides a standardized, machine-readable format for documenting: + +- **Component Catalogs** - What UI components a platform provides +- **SDK Bindings** - How to import/use components from platform SDKs +- **Requirement Levels** - Whether platform components are required, recommended, or optional +- **Custom Component Policies** - Whether developers can bring their own (BYO) components +- **Publishing Constraints** - Different rules for public vs private apps +- **Rendering Engines** - How UI definitions translate to rendered interfaces + +## Target Foundation + +Fenestra is designed for submission to the **[OpenAPI Initiative (OAI)](https://www.openapis.org/)**, a Linux Foundation Collaborative Project that governs: + +- **OpenAPI Specification** - The industry standard for describing REST APIs +- **Arazzo Specification** - Workflow orchestration for API sequences (released 2024) +- **Overlay Specification** - API document composition and extension + +The OAI has demonstrated success in standardizing API descriptions. Fenestra extends this model to UI component ecosystems, complementing API and workflow descriptions with UI capability descriptions. + +## Relationship to Other Specifications + +| Specification | Purpose | Fenestra Integration | +|--------------|---------|---------------------| +| **OpenAPI** | API description | Fenestra extends OpenAPI patterns for UI description | +| **Arazzo** | Workflow orchestration | Workflow steps can reference Fenestra UI for user interactions | +| **MCP Apps** | AI-driven UI resources | Fenestra components map to MCP App templates | +| **JSON Forms** | Schema-driven forms | Fenestra supports JSON Schema-based rendering | + +## Why Fenestra? + +Modern platforms provide wildly different approaches to UI extensibility: + +| Platform | SDK | Requirement Level | Custom Components | +|----------|-----|-------------------|-------------------| +| **HubSpot** | `@hubspot/ui-extensions` | Required | Not allowed | +| **Canva** | `@canva/app-ui-kit` | Strongly recommended for public apps | Limited | +| **Salesforce** | Lightning Web Components | Required for Lightning Experience | Via LWC only | +| **Miro** | Web SDK + Mirotone CSS | Optional | Fully allowed | +| **Front** | `@frontapp/ui-kit` | Recommended | Allowed | + +Fenestra provides a unified way to describe these differences, enabling: + +1. **Tooling** - Code generators, validators, and IDE plugins that understand platform constraints +2. **Documentation** - Consistent documentation across platforms +3. **Cross-platform portability** - Map components between platforms via web standard mappings +4. **AI agents** - LLMs can understand platform UI capabilities from structured descriptions + +## Specification Structure + +```yaml +fenestra: "0.1.0" + +info: + title: "Platform Name UI Ecosystem" + version: "1.0.0" + +platform: + name: "PlatformName" + vendor: "Company" + documentation: "https://developers.platform.com" + +sdks: + main-sdk: + package: "@platform/ui-components" + packageManager: npm + exports: + Button: { type: component } + TextField: { type: component } + +componentCatalog: + components: + Button: + name: "Button" + category: action + sdkBinding: + sdk: main-sdk + export: Button + webStandardMapping: + htmlElement: button + ariaRole: button + +policies: + componentRequirement: + level: required | recommended | optional + scope: all | publicApps | marketplaceApps + + customComponents: + allowed: true | false + constraints: + - mustFollowDesignSystem + - requiresReview + + publishing: + privateApps: + componentRequirement: optional + customComponentsAllowed: true + publicApps: + componentRequirement: required + reviewRequired: true +``` + +## Key Concepts + +### Component Requirement Levels + +- **required** - Must use platform components exclusively (e.g., HubSpot) +- **recommended** - Platform components preferred, alternatives allowed with caveats (e.g., Canva) +- **optional** - Platform components available but not required (e.g., Miro) + +### Publishing Scope + +Requirements often differ based on app visibility: + +- **Private apps** - Internal use only, more flexibility +- **Public apps** - Shared with others, stricter requirements +- **Marketplace apps** - Published to official store, strictest requirements + certification + +### Custom Component Policies + +Platforms vary in allowing custom/BYO components: + +- **Not allowed** - Must use SDK components only +- **Allowed with constraints** - Must wrap platform primitives, follow design system +- **Fully allowed** - Complete freedom (rare in enterprise platforms) + +### Web Standard Mappings + +Components map to web platform standards for semantic understanding: + +```yaml +webStandardMapping: + htmlElement: button # Closest HTML element + ariaRole: button # ARIA role for accessibility + semanticType: action # UI pattern category +``` + +## Integration with MCP Apps + +The [MCP Apps specification](https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/) enables AI-driven UI through the Model Context Protocol. Fenestra components can be: + +1. **Mapped to MCP App templates** - Platform components reference predeclared templates +2. **Exposed as UI resources** - Components declared in MCP server manifests +3. **Bound to tools** - UI surfaces linked to MCP tool invocations + +```yaml +mcpAppsIntegration: + supported: true + templateMappings: + form: JSONFormsRenderer + confirmation: ConfirmDialog + communicationProtocol: jsonRpc +``` + +## Integration with JSON Forms + +[JSON Forms](https://jsonforms.io/) enables declarative form rendering from JSON Schema. Fenestra describes how platforms support this: + +```yaml +jsonFormsIntegration: + supported: true + rendererSet: platform # Uses platform's own renderers + customRenderersAllowed: true + componentBindings: + text: TextField + number: NumberInput + boolean: Checkbox + array: DynamicList +``` + +## Examples + +See the `/examples` directory for complete Fenestra documents describing real platforms: + +- [hubspot.fenestra.yaml](./examples/hubspot.fenestra.yaml) - HubSpot UI Extensions +- [canva.fenestra.yaml](./examples/canva.fenestra.yaml) - Canva App UI Kit +- [miro.fenestra.yaml](./examples/miro.fenestra.yaml) - Miro Developer Platform + +## Current Limitations & Roadmap + +This is an early draft. See [ISSUES.md](./ISSUES.md) for known gaps including: + +- **Declarative UI** - JSON-based UI patterns (Slack Block Kit, Adaptive Cards) not yet supported +- **Mobile Platforms** - iOS/Android SDK ecosystems not addressed +- **MCP Apps** - Integration schema needs expansion for tool-to-UI bindings +- **Compliance** - Accessibility standards, security certifications, privacy regulations +- **Policy Granularity** - Per-category and per-extension-point requirements + +## Contributing + +This specification is a draft under development. Contributions welcome: + +1. **Review** - Read the spec and examples, provide feedback +2. **Issues** - Open issues for gaps, edge cases, or unclear sections +3. **Examples** - Add Fenestra documents for additional platforms +4. **PRs** - Submit improvements to the specification schema + +## Related Work + +- [MCP Apps Proposal](https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/) - UI extension for Model Context Protocol +- [JSON Forms](https://jsonforms.io/) - JSON Schema-based form rendering +- [HubSpot UI Extensions](https://developers.hubspot.com/docs/platform/ui-extensions-overview) +- [Canva App UI Kit](https://www.canva.dev/docs/apps/app-ui-kit/) +- [Salesforce LWC](https://developer.salesforce.com/developer-centers/lightning-web-components) +- [Miro Developer Platform](https://developers.miro.com/) +- [Front Plugin SDK](https://dev.frontapp.com/docs/plugin-overview) + +## License + +Apache 2.0 diff --git a/specs/fenestra/examples/hubspot.fenestra.yaml b/specs/fenestra/examples/hubspot.fenestra.yaml new file mode 100644 index 0000000..62b92bf --- /dev/null +++ b/specs/fenestra/examples/hubspot.fenestra.yaml @@ -0,0 +1,352 @@ +# Fenestra Document: HubSpot UI Extensions +# +# HubSpot represents the "required components" end of the spectrum. +# Developers MUST use the provided SDK components exclusively. + +fenestra: "0.1.0" + +info: + title: HubSpot UI Extensions Ecosystem + version: "1.0.0" + description: | + HubSpot's UI Extensions SDK provides React-based components for building + CRM cards, custom tabs, and sidebar extensions within HubSpot. + + Key characteristic: Component usage is REQUIRED - you can only use + components provided through the UI Extensions SDK. + +platform: + name: HubSpot + vendor: HubSpot, Inc. + documentation: https://developers.hubspot.com/docs/platform/ui-extensions-overview + appMarketplace: https://ecosystem.hubspot.com/marketplace/apps + +sdks: + hubspot-ui-extensions: + name: HubSpot UI Extensions SDK + packageManager: npm + package: "@hubspot/ui-extensions" + version: "^0.11.2" + repository: https://github.com/HubSpot/ui-extensions-examples + documentation: https://developers.hubspot.com/docs/platform/ui-extensions-sdk + exports: + # Layout Components + Flex: + type: component + description: Flexbox layout container + Box: + type: component + description: Generic box container + Divider: + type: component + description: Visual separator + Tile: + type: component + description: Card-like container + + # Action Components + Button: + type: component + description: Primary action button + ButtonRow: + type: component + description: Row of action buttons + Link: + type: component + description: Navigation link + + # Input Components + Input: + type: component + description: Text input field + TextArea: + type: component + description: Multi-line text input + Select: + type: component + description: Dropdown selection + DateInput: + type: component + description: Date picker + NumberInput: + type: component + description: Numeric input + Toggle: + type: component + description: Boolean toggle switch + Checkbox: + type: component + description: Checkbox input + + # Display Components + Text: + type: component + description: Text display + Heading: + type: component + description: Section heading + Alert: + type: component + description: Alert/notification message + Badge: + type: component + description: Status badge + Tag: + type: component + description: Label tag + Image: + type: component + description: Image display + Table: + type: component + description: Data table + DescriptionList: + type: component + description: Key-value list + ProgressBar: + type: component + description: Progress indicator + LoadingSpinner: + type: component + description: Loading state indicator + EmptyState: + type: component + description: Empty state placeholder + ErrorState: + type: component + description: Error state display + + # Overlay Components + Modal: + type: component + description: Modal dialog + since: "0.10.0" + Panel: + type: component + description: Slide-out panel + since: "0.10.0" + + # Form Components + Form: + type: component + description: Form container with validation + + subpackages: + crm: + package: "@hubspot/ui-extensions/crm" + description: CRM-specific components that fetch data from records + exports: + CrmAssociationTable: + type: component + description: Table of associated CRM records + CrmPropertyList: + type: component + description: List of CRM record properties + CrmActionButton: + type: component + description: Button that performs CRM actions + CrmCardActions: + type: component + description: Card action buttons + +componentCatalog: + categories: + layout: + name: Layout + description: Components for organizing content + components: [Flex, Box, Divider, Tile] + + action: + name: Actions + description: Interactive elements for user actions + components: [Button, ButtonRow, Link] + + input: + name: Inputs + description: Form input components + components: [Input, TextArea, Select, DateInput, NumberInput, Toggle, Checkbox] + + display: + name: Display + description: Components for showing information + components: [Text, Heading, Alert, Badge, Tag, Image, Table, DescriptionList] + + feedback: + name: Feedback + description: Loading and state indicators + components: [ProgressBar, LoadingSpinner, EmptyState, ErrorState] + + overlay: + name: Overlays + description: Modal and panel components + components: [Modal, Panel] + + components: + Button: + name: Button + description: Primary action button with variants + category: action + sdkBinding: + sdk: hubspot-ui-extensions + export: Button + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + variant: + type: string + enum: [primary, secondary, destructive] + default: primary + onClick: + type: function + description: Click handler + disabled: + type: boolean + default: false + type: + type: string + enum: [button, submit, reset] + variants: + - primary + - secondary + - destructive + accessibility: + keyboardSupport: true + screenReaderSupport: true + + Modal: + name: Modal + description: Pop-up dialog for confirmations and short forms + category: overlay + sdkBinding: + sdk: hubspot-ui-extensions + export: Modal + webStandardMapping: + htmlElement: dialog + ariaRole: dialog + semanticType: container + props: + title: + type: string + description: Modal title + variant: + type: string + enum: [default, danger] + description: Use danger for destructive action confirmations + slots: + default: + description: Modal content + required: true + accessibility: + keyboardSupport: true + screenReaderSupport: true + focusManagement: "Focus trapped within modal" + + Panel: + name: Panel + description: Slide-out sidebar for complex tasks + category: overlay + sdkBinding: + sdk: hubspot-ui-extensions + export: Panel + webStandardMapping: + htmlElement: aside + ariaRole: complementary + semanticType: container + props: + title: + type: string + description: Panel header title + slots: + default: + description: Panel content + required: true + +policies: + componentRequirement: + level: required + scope: all + rationale: | + HubSpot enforces exclusive use of SDK components to ensure + consistent user experience and security across all extensions. + + customComponents: + allowed: false + documentation: https://developers.hubspot.com/docs/platform/ui-extension-components + constraints: [] + + publishing: + privateApps: + componentRequirement: required + customComponentsAllowed: false + reviewRequired: false + notes: "Private apps still require SDK components" + + publicApps: + componentRequirement: required + customComponentsAllowed: false + reviewRequired: true + designReviewRequired: true + notes: "Public apps undergo review before marketplace listing" + + marketplaceApps: + componentRequirement: required + customComponentsAllowed: false + certificationRequired: true + notes: "Marketplace apps require full certification" + + designGuidelines: + required: true + designSystem: "HubSpot Canvas" + designSystemUrl: https://canvas.hubspot.com/ + designTokensProvided: false + +extensionPoints: + - id: crm-card + name: CRM Record Card + type: card + description: Card displayed on CRM record pages + supportedComponents: + - all + constraints: + responsive: true + context: + provides: + - currentRecord + - user + actions: + - addNote + - createTask + - updateProperty + + - id: crm-sidebar + name: CRM Sidebar Panel + type: sidebar + description: Panel in the right sidebar of CRM records + supportedComponents: + - all + context: + provides: + - currentRecord + - associations + - user + +renderingEngines: + react: + type: react + name: React Rendering + description: All extensions render as React components + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + +jsonFormsIntegration: + supported: false + notes: "HubSpot uses its own Form component, not JSON Forms" + +mcpAppsIntegration: + supported: false + notes: "Not yet integrated with MCP Apps specification" diff --git a/specs/fenestra/examples/miro.fenestra.yaml b/specs/fenestra/examples/miro.fenestra.yaml new file mode 100644 index 0000000..6fe61ff --- /dev/null +++ b/specs/fenestra/examples/miro.fenestra.yaml @@ -0,0 +1,276 @@ +# Fenestra Document: Miro Developer Platform +# +# Miro represents the "optional components" end of the spectrum. +# The Mirotone library is provided but developers have full freedom. + +fenestra: "0.1.0" + +info: + title: Miro Developer Platform UI Ecosystem + version: "1.0.0" + description: | + Miro's Developer Platform provides the Web SDK for board interactions + and Mirotone as an optional CSS component library for native-feeling UIs. + + Key characteristic: Component usage is OPTIONAL - developers can use + Mirotone, their own components, or any framework they prefer. + +platform: + name: Miro + vendor: Miro, Inc. + documentation: https://developers.miro.com/ + appMarketplace: https://miro.com/marketplace/ + +sdks: + miro-web-sdk: + name: Miro Web SDK + packageManager: npm + package: "@mirohq/websdk-types" + documentation: https://developers.miro.com/docs/miro-web-sdk-introduction + exports: + miro: + type: utility + description: Global miro object for board interactions + + mirotone: + name: Mirotone CSS Library + packageManager: npm + package: "mirotone" + repository: https://github.com/miroapp/mirotone + documentation: https://www.mirotone.xyz/ + description: | + Lightweight CSS component library that styles HTML to match Miro's UI. + Unlike React component libraries, Mirotone works with plain HTML. + exports: + # Mirotone uses CSS classes, not component exports + # Listed here for documentation purposes + button: + type: component + description: ".button class for buttons" + input: + type: component + description: ".input class for text inputs" + select: + type: component + description: ".select class for dropdowns" + checkbox: + type: component + description: ".checkbox class for checkboxes" + radio: + type: component + description: ".radio class for radio buttons" + tabs: + type: component + description: ".tabs class for tab navigation" + tooltip: + type: component + description: ".tooltip class for tooltips" + modal: + type: component + description: ".modal class for modal dialogs" + +componentCatalog: + categories: + action: + name: Actions + description: Interactive elements + components: [button] + + input: + name: Inputs + description: Form controls + components: [input, select, checkbox, radio, textarea] + + navigation: + name: Navigation + description: Navigation components + components: [tabs, sidebar] + + overlay: + name: Overlays + description: Modal and tooltip components + components: [modal, tooltip] + + components: + button: + name: Button + description: Mirotone button styling + category: action + sdkBinding: + sdk: mirotone + export: button + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + class: + type: string + description: "CSS class: .button, .button.button-primary, .button.button-danger" + variants: + - default + - primary + - secondary + - danger + examples: + - title: Primary Button + code: | + + language: html + - title: Icon Button + code: | + + language: html + + modal: + name: Modal + description: Mirotone modal dialog + category: overlay + sdkBinding: + sdk: mirotone + export: modal + webStandardMapping: + htmlElement: dialog + ariaRole: dialog + semanticType: container + examples: + - title: Basic Modal + code: | + + language: html + +policies: + componentRequirement: + level: optional + scope: all + rationale: | + Miro provides Mirotone as a convenience library but does not + require its use. Developers have complete freedom in their + UI implementation choices. + + customComponents: + allowed: true + constraints: [] + registrationRequired: false + approvalRequired: false + documentation: https://developers.miro.com/docs/build-and-deploy-your-app + + publishing: + privateApps: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: false + notes: "Complete freedom for private apps" + + publicApps: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: true + notes: "Review focuses on functionality, not UI implementation" + + marketplaceApps: + componentRequirement: optional + customComponentsAllowed: true + certificationRequired: true + notes: "Certification covers security and functionality" + + designGuidelines: + required: false + designSystem: "Mirotone" + designSystemUrl: https://www.mirotone.xyz/ + designTokensProvided: true + +extensionPoints: + - id: app-panel + name: App Panel + type: panel + description: Panel that opens from the app icon in the left toolbar + supportedComponents: + - all + constraints: + maxWidth: 320 + responsive: false + context: + provides: + - selectedItems + - viewport + - board + - user + actions: + - createItem + - updateItem + - deleteItem + - zoomTo + + - id: modal + name: Modal Dialog + type: modal + description: Full modal overlay opened via SDK + supportedComponents: + - all + constraints: + maxWidth: 600 + maxHeight: 400 + responsive: true + context: + provides: + - selectedItems + - board + - user + + - id: board-item + name: Board Item + type: canvas + description: Custom items rendered on the board canvas + supportedComponents: + - iframe-based + constraints: + responsive: true + context: + provides: + - itemData + - board + - user + +renderingEngines: + html-css: + type: custom + name: HTML + CSS + description: Plain HTML styled with Mirotone CSS classes + + any-framework: + type: custom + name: Any Framework + description: React, Vue, Svelte, vanilla JS - developer's choice + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + +jsonFormsIntegration: + supported: true + rendererSet: custom + customRenderersAllowed: true + notes: "Developers can integrate JSON Forms with their own renderers" + +mcpAppsIntegration: + supported: false + notes: "Potential future integration via iframe embedding" diff --git a/specs/fenestra/fenestra-spec.yaml b/specs/fenestra/fenestra-spec.yaml new file mode 100644 index 0000000..25603e8 --- /dev/null +++ b/specs/fenestra/fenestra-spec.yaml @@ -0,0 +1,922 @@ +# Fenestra Specification +# Version: 0.1.0-draft +# +# A specification for describing platform UI component ecosystems, SDK bindings, +# and UI rendering capabilities in a standardized, machine-readable format. +# +# Designed for submission to the OpenAPI Initiative (OAI), a Linux Foundation +# Collaborative Project, to complement OpenAPI, Arazzo, and emerging specifications +# like MCP Apps. + +openapi: 3.1.0 +info: + title: Fenestra Specification + version: 0.1.0-draft + description: | + # Fenestra Specification + + **Fenestra** (Latin for "window") is a specification for describing how platforms + expose UI component ecosystems to developers building integrations, apps, and extensions. + + ## Purpose + + Modern platforms (HubSpot, Salesforce, Canva, Miro, Front, Slack, etc.) provide + UI extension points with varying degrees of flexibility. Fenestra standardizes + the description of: + + 1. **Component Catalogs** - What UI components a platform provides + 2. **SDK Bindings** - How to import and use components from platform SDKs + 3. **Requirement Levels** - Whether platform components are required, recommended, or optional + 4. **Custom Component Policies** - Whether developers can bring their own components + 5. **Publishing Constraints** - Different rules for public vs private apps + 6. **Rendering Engines** - How UI definitions translate to rendered interfaces + + ## Relationship to Other Specifications + + - **OpenAPI**: Fenestra extends OpenAPI patterns for UI description + - **Arazzo**: Workflow sequences can reference Fenestra UI definitions for user interactions + - **MCP Apps**: Fenestra component definitions can map to MCP App UI resources + - **JSON Forms/JSON Schema**: Fenestra supports JSON Schema-based UI rendering + + contact: + name: Fenestra Working Group + url: https://github.com/friggframework/fenestra-spec + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + +# ============================================================================= +# FENESTRA SPECIFICATION SCHEMA +# ============================================================================= + +components: + schemas: + + # ========================================================================= + # ROOT DOCUMENT + # ========================================================================= + + FenestraDocument: + type: object + required: + - fenestra + - info + properties: + fenestra: + type: string + description: Fenestra specification version + pattern: '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$' + example: "0.1.0" + + info: + $ref: '#/components/schemas/Info' + + platform: + $ref: '#/components/schemas/Platform' + + sdks: + type: object + description: SDK ecosystem definitions indexed by SDK identifier + additionalProperties: + $ref: '#/components/schemas/SDK' + + componentCatalog: + $ref: '#/components/schemas/ComponentCatalog' + + renderingEngines: + type: object + description: Supported rendering engine configurations + additionalProperties: + $ref: '#/components/schemas/RenderingEngine' + + policies: + $ref: '#/components/schemas/Policies' + + extensionPoints: + type: array + description: Where UI can be injected in the host platform + items: + $ref: '#/components/schemas/ExtensionPoint' + + # ========================================================================= + # INFO OBJECT + # ========================================================================= + + Info: + type: object + required: + - title + - version + properties: + title: + type: string + description: Human-readable name of this Fenestra document + version: + type: string + description: Version of this document + description: + type: string + description: Extended description (CommonMark supported) + termsOfService: + type: string + format: uri + contact: + type: object + properties: + name: + type: string + url: + type: string + format: uri + email: + type: string + format: email + license: + type: object + properties: + name: + type: string + url: + type: string + format: uri + + # ========================================================================= + # PLATFORM OBJECT + # ========================================================================= + + Platform: + type: object + description: | + Describes the host platform that provides the UI extension capabilities. + required: + - name + properties: + name: + type: string + description: Platform name + examples: + - HubSpot + - Salesforce + - Canva + - Miro + - Front + - Slack + + vendor: + type: string + description: Platform vendor/company name + + documentation: + type: string + format: uri + description: URL to platform developer documentation + + appMarketplace: + type: string + format: uri + description: URL to the platform's app marketplace/directory + + # ========================================================================= + # SDK OBJECT + # ========================================================================= + + SDK: + type: object + description: | + Describes an SDK package that provides UI components or utilities. + SDKs can be required, recommended, or optional depending on platform policies. + required: + - name + - packageManager + - package + properties: + name: + type: string + description: Human-readable SDK name + examples: + - "HubSpot UI Extensions" + - "Canva App UI Kit" + - "Salesforce Lightning Web Components" + + packageManager: + type: string + description: Package manager ecosystem + enum: + - npm + - yarn + - pip + - maven + - gradle + - nuget + - cargo + - go + - composer + default: npm + + package: + type: string + description: Package identifier (e.g., npm package name) + examples: + - "@hubspot/ui-extensions" + - "@canva/app-ui-kit" + - "lightning/ui" + + version: + type: string + description: Recommended or minimum version + examples: + - "^0.11.2" + - ">=1.0.0" + + repository: + type: string + format: uri + description: Source code repository URL + + documentation: + type: string + format: uri + description: SDK documentation URL + + exports: + type: object + description: Named exports from the SDK package + additionalProperties: + $ref: '#/components/schemas/SDKExport' + + subpackages: + type: object + description: | + Additional subpackages within the SDK ecosystem. + Some SDKs split components across multiple packages. + additionalProperties: + type: object + properties: + package: + type: string + description: + type: string + exports: + type: object + additionalProperties: + $ref: '#/components/schemas/SDKExport' + + SDKExport: + type: object + description: A named export from an SDK package + properties: + type: + type: string + enum: + - component + - hook + - utility + - icon + - token + - context + - type + description: Type of export + + description: + type: string + description: What this export provides + + deprecated: + type: boolean + default: false + + since: + type: string + description: Version when this export was added + + # ========================================================================= + # COMPONENT CATALOG + # ========================================================================= + + ComponentCatalog: + type: object + description: | + The catalog of UI components available on this platform. + Components can be categorized and mapped to web standards. + properties: + categories: + type: object + description: Component categories (layout, input, display, etc.) + additionalProperties: + $ref: '#/components/schemas/ComponentCategory' + + components: + type: object + description: All components indexed by canonical identifier + additionalProperties: + $ref: '#/components/schemas/Component' + + ComponentCategory: + type: object + properties: + name: + type: string + description: + type: string + components: + type: array + items: + type: string + description: References to component identifiers in this category + + Component: + type: object + required: + - name + properties: + name: + type: string + description: Component display name + + description: + type: string + description: What this component does + + category: + type: string + description: Category this component belongs to + examples: + - layout + - input + - display + - navigation + - overlay + - feedback + - data + + sdkBinding: + $ref: '#/components/schemas/SDKBinding' + + webStandardMapping: + $ref: '#/components/schemas/WebStandardMapping' + + props: + type: object + description: Component properties/attributes (JSON Schema format) + additionalProperties: true + + slots: + type: object + description: Named slots/children this component accepts + additionalProperties: + $ref: '#/components/schemas/Slot' + + events: + type: object + description: Events this component can emit + additionalProperties: + $ref: '#/components/schemas/ComponentEvent' + + variants: + type: array + description: Visual or behavioral variants + items: + type: string + + accessibility: + $ref: '#/components/schemas/AccessibilityInfo' + + examples: + type: array + items: + $ref: '#/components/schemas/ComponentExample' + + SDKBinding: + type: object + description: How to import this component from an SDK + required: + - sdk + - export + properties: + sdk: + type: string + description: Reference to SDK identifier in the sdks object + + subpackage: + type: string + description: Subpackage within the SDK (if applicable) + + export: + type: string + description: Named export from the package + + importPath: + type: string + description: | + Full import path if different from default package. + Example: "@hubspot/ui-extensions/crm" + + WebStandardMapping: + type: object + description: | + Maps this platform component to web platform standards. + Enables cross-platform compatibility and semantic understanding. + properties: + htmlElement: + type: string + description: Closest HTML element equivalent + examples: + - button + - input + - select + - dialog + - form + + ariaRole: + type: string + description: ARIA role this component fulfills + examples: + - button + - textbox + - listbox + - dialog + - alert + + webComponent: + type: string + description: Web Components standard equivalent (if any) + + semanticType: + type: string + description: Semantic UI pattern type + enum: + - action + - input + - display + - layout + - navigation + - feedback + - container + + Slot: + type: object + properties: + description: + type: string + required: + type: boolean + default: false + accepts: + type: array + description: Component types this slot accepts + items: + type: string + + ComponentEvent: + type: object + properties: + description: + type: string + payload: + type: object + description: JSON Schema for event payload + + AccessibilityInfo: + type: object + properties: + keyboardSupport: + type: boolean + screenReaderSupport: + type: boolean + focusManagement: + type: string + notes: + type: string + + ComponentExample: + type: object + properties: + title: + type: string + description: + type: string + code: + type: string + description: Example code snippet + language: + type: string + default: jsx + + # ========================================================================= + # RENDERING ENGINES + # ========================================================================= + + RenderingEngine: + type: object + description: | + A rendering engine that can interpret UI definitions and produce rendered output. + Supports multiple paradigms: declarative JSON, React components, web components, etc. + required: + - type + properties: + type: + type: string + enum: + - jsonForms + - jsonSchema + - mcpApps + - react + - webComponents + - lwc + - custom + description: Rendering paradigm + + name: + type: string + description: Human-readable engine name + + description: + type: string + + schemaSupport: + type: object + description: Schema-based rendering configuration + properties: + dataSchema: + type: string + enum: + - jsonSchema + - custom + description: Schema format for data definition + + uiSchema: + type: string + enum: + - jsonFormsUISchema + - mcpAppsTemplate + - custom + description: Schema format for UI definition + + customRenderers: + type: boolean + description: Whether custom renderers can be registered + default: false + + sandboxing: + $ref: '#/components/schemas/SandboxConfig' + + SandboxConfig: + type: object + description: Security sandboxing configuration for rendered UI + properties: + iframeSandbox: + type: boolean + description: Whether UI runs in sandboxed iframe + + sandboxAttributes: + type: array + items: + type: string + description: iframe sandbox attribute values + examples: + - allow-scripts + - allow-forms + - allow-same-origin + + cspPolicy: + type: string + description: Content Security Policy for rendered content + + # ========================================================================= + # POLICIES + # ========================================================================= + + Policies: + type: object + description: | + Platform policies governing UI component usage, custom components, + and publishing requirements. + properties: + + componentRequirement: + $ref: '#/components/schemas/ComponentRequirementPolicy' + + customComponents: + $ref: '#/components/schemas/CustomComponentPolicy' + + publishing: + $ref: '#/components/schemas/PublishingPolicy' + + designGuidelines: + $ref: '#/components/schemas/DesignGuidelinesPolicy' + + ComponentRequirementPolicy: + type: object + description: | + Whether platform-provided components are required. + + Examples: + - HubSpot: Required (can only use SDK components) + - Canva: Strongly recommended for public apps + - Miro: Optional (Mirotone is available but not required) + properties: + level: + type: string + enum: + - required + - recommended + - optional + description: | + - required: Must use platform components exclusively + - recommended: Platform components preferred, alternatives allowed + - optional: Platform components available but not required + + scope: + type: string + enum: + - all + - publicApps + - marketplaceApps + description: What app types this requirement applies to + + rationale: + type: string + description: Why this policy exists + + exceptions: + type: array + items: + type: string + description: Documented exceptions to this policy + + CustomComponentPolicy: + type: object + description: | + Whether developers can bring their own (BYO) components. + + Key dimensions: + - Allowed at all? + - Must wrap platform primitives? + - Must follow design system? + - Review required for marketplace? + properties: + allowed: + type: boolean + description: Whether custom components are permitted at all + + constraints: + type: array + items: + type: string + enum: + - mustWrapPlatformPrimitives + - mustFollowDesignSystem + - mustPassAccessibilityAudit + - requiresReview + - sandboxOnly + description: Constraints on custom components + + registrationRequired: + type: boolean + description: Whether custom components must be registered + default: false + + approvalRequired: + type: boolean + description: Whether custom components require platform approval + default: false + + documentation: + type: string + format: uri + description: Documentation for custom component requirements + + PublishingPolicy: + type: object + description: | + Different rules for public/marketplace apps vs private/internal apps. + + Common pattern: + - Private apps: More flexibility, fewer requirements + - Public apps: Strict component requirements, review process + properties: + + privateApps: + type: object + properties: + componentRequirement: + type: string + enum: [required, recommended, optional] + customComponentsAllowed: + type: boolean + reviewRequired: + type: boolean + notes: + type: string + + publicApps: + type: object + properties: + componentRequirement: + type: string + enum: [required, recommended, optional] + customComponentsAllowed: + type: boolean + reviewRequired: + type: boolean + designReviewRequired: + type: boolean + accessibilityAuditRequired: + type: boolean + notes: + type: string + + marketplaceApps: + type: object + description: Apps published to official marketplace (may differ from public) + properties: + componentRequirement: + type: string + enum: [required, recommended, optional] + customComponentsAllowed: + type: boolean + certificationRequired: + type: boolean + notes: + type: string + + DesignGuidelinesPolicy: + type: object + description: Platform design system and guidelines + properties: + required: + type: boolean + description: Whether following guidelines is mandatory + + designSystem: + type: string + description: Name of the design system + examples: + - "Lightning Design System" + - "Canva Design Guidelines" + - "HubSpot Canvas" + + designSystemUrl: + type: string + format: uri + + designTokensProvided: + type: boolean + description: Whether design tokens are available for custom styling + + # ========================================================================= + # EXTENSION POINTS + # ========================================================================= + + ExtensionPoint: + type: object + description: | + A location in the host platform where UI can be injected. + + Examples: + - Sidebar panel + - Modal dialog + - Card on a record page + - Toolbar button + - Canvas element (Miro, Canva) + required: + - id + - name + - type + properties: + id: + type: string + description: Unique identifier for this extension point + + name: + type: string + description: Human-readable name + + type: + type: string + enum: + - sidebar + - modal + - panel + - card + - toolbar + - contextMenu + - canvas + - composer + - fullPage + - embedded + description: Type of extension point + + description: + type: string + + supportedComponents: + type: array + items: + type: string + description: Component types allowed at this extension point + + constraints: + type: object + properties: + maxWidth: + type: integer + description: Maximum width in pixels + maxHeight: + type: integer + description: Maximum height in pixels + responsive: + type: boolean + description: Whether extension must be responsive + + context: + type: object + description: Data context available at this extension point + properties: + provides: + type: array + items: + type: string + description: Context data types provided + examples: + - currentRecord + - selectedItems + - user + - conversation + + actions: + type: array + items: + type: string + description: Actions that can be performed from this context + + # ========================================================================= + # MCP APPS INTEGRATION + # ========================================================================= + + MCPAppsIntegration: + type: object + description: | + Integration with MCP Apps specification for AI-driven UI. + Maps Fenestra components to MCP Apps UI resources. + properties: + supported: + type: boolean + description: Whether this platform supports MCP Apps + + templateMappings: + type: object + description: Maps MCP App templates to Fenestra components + additionalProperties: + type: string + + customTemplatesAllowed: + type: boolean + description: Whether custom MCP App templates are allowed + + communicationProtocol: + type: string + enum: + - jsonRpc + - postMessage + - custom + description: Protocol for host-UI communication + + # ========================================================================= + # JSON FORMS INTEGRATION + # ========================================================================= + + JSONFormsIntegration: + type: object + description: | + Integration with JSON Forms specification for schema-driven UI. + Enables declarative form rendering from JSON Schema. + properties: + supported: + type: boolean + description: Whether this platform supports JSON Forms rendering + + rendererSet: + type: string + enum: + - default + - material + - vanilla + - platform + - custom + description: Which JSON Forms renderer set to use + + customRenderersAllowed: + type: boolean + description: Whether custom JSON Forms renderers can be registered + + componentBindings: + type: object + description: Maps JSON Forms control types to platform components + additionalProperties: + type: string + examples: + text: TextField + number: NumberInput + boolean: Checkbox + date: DatePicker From 46a8a1fa2ed2e7bedbeaa6201ebbaaefbe62e7ef Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Dec 2025 05:02:58 +0000 Subject: [PATCH 02/22] Add extension type diagrams and task tracking Created DIAGRAMS.md with ASCII diagrams showing render flow for each type: 1. JSON Response - Platform renders pre-built components from JSON 2. Coded Components - Developer React code with platform UI Kit 3. Iframe - Full HTML/JS/CSS freedom in iframe 4. Embedded SDK - Platform SDK embedded in developer's app Also added TASKS.md to track progress on spec development. --- specs/fenestra/DIAGRAMS.md | 392 +++++++++++++++++++++++++++++++++++++ specs/fenestra/TASKS.md | 97 +++++++++ 2 files changed, 489 insertions(+) create mode 100644 specs/fenestra/DIAGRAMS.md create mode 100644 specs/fenestra/TASKS.md diff --git a/specs/fenestra/DIAGRAMS.md b/specs/fenestra/DIAGRAMS.md new file mode 100644 index 0000000..611f939 --- /dev/null +++ b/specs/fenestra/DIAGRAMS.md @@ -0,0 +1,392 @@ +# Fenestra Extension Types - Diagrams + +This document illustrates the 4 broad extension types and how rendering flows from developer-provided assets to user-visible UI. + +--- + +## Type 1: JSON Response + +**Pattern**: Developer provides JSON conforming to platform schema → Platform renders pre-built components + +**Examples**: Google Workspace Add-ons, Asana App Components, Slack Block Kit, Pipedrive, Gorgias + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLATFORM SIDE │ +│ │ +│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────────────┐│ +│ │ User │ │ Platform │ │ Component Renderer ││ +│ │ Triggers │───▶│ Calls │ │ (Platform-owned) ││ +│ │ Action │ │ Endpoint │ │ ││ +│ └─────────────┘ └──────┬───────┘ │ ┌─────┐ ┌─────┐ ┌─────┐ ││ +│ │ │ │Card │ │Form │ │List │ ... ││ +│ │ │ └─────┘ └─────┘ └─────┘ ││ +│ ▼ └────────────────┬────────────────┘│ +│ ┌──────────────┐ │ │ +│ │ Validate │ │ │ +│ │ JSON │ │ │ +│ │ Schema │ │ │ +│ └──────┬───────┘ │ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌──────────────────────────────────────┐ │ +│ │ Rendered UI in Platform │ │ +│ └──────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ + ▲ + │ HTTP Response + │ (JSON Payload) +┌────────────────────────────┴────────────────────────────────────────────────┐ +│ DEVELOPER SIDE │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Developer's Server │ │ +│ │ │ │ +│ │ 1. Receive request with context │ │ +│ │ 2. Fetch/compute data │ │ +│ │ 3. Return JSON matching platform schema │ │ +│ │ │ │ +│ │ Example Response: │ │ +│ │ { │ │ +│ │ "type": "card", │ │ +│ │ "title": "Customer Info", │ │ +│ │ "sections": [ │ │ +│ │ { "type": "keyValue", "key": "Name", "value": "John" } │ │ +│ │ ] │ │ +│ │ } │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Developer provides: Endpoint URL, JSON responses │ +│ Developer does NOT provide: Any rendering code, components, or UI logic │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Key Characteristics**: +- No JS SDK typically needed +- Platform owns ALL rendering +- Developer only controls data and which component types to use +- Limited customization (can't create new component types) +- Fast to build, but constrained + +--- + +## Type 2: Coded Components + +**Pattern**: Developer writes React code using platform's UI Kit → Code runs in platform's runtime + +**Examples**: Salesforce LWC, HubSpot UI Extensions, Zendesk Apps, Canva Apps SDK + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLATFORM SIDE │ +│ │ +│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │ +│ │ User │ │ Platform Runtime │ │ +│ │ Opens │───▶│ │ │ +│ │ Extension │ │ ┌────────────────────────────────────────────┐ │ │ +│ └─────────────┘ │ │ Sandboxed Execution Environment │ │ │ +│ │ │ │ │ │ +│ │ │ ┌──────────────────────────────────────┐ │ │ │ +│ │ │ │ Developer's React Code │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ import { Button, Card } from SDK │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ └──────────────────────────────────────┘ │ │ │ +│ │ │ │ │ │ │ +│ │ │ ▼ │ │ │ +│ │ │ ┌──────────────────────────────────────┐ │ │ │ +│ │ │ │ Platform UI Kit Components │ │ │ │ +│ │ │ │ (Button, Card, Input, Modal...) │ │ │ │ +│ │ │ └──────────────────────────────────────┘ │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │ ┌────────────────────────────────────────────┐ │ │ +│ │ │ Optional: JS SDK for host interaction │ │ │ +│ │ │ hubspot.crm.actions.openModal() │ │ │ +│ │ │ hubspot.ui.showToast() │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ └──────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ + ▲ + │ Bundle (JS/CSS) + │ +┌────────────────────────────┴────────────────────────────────────────────────┐ +│ DEVELOPER SIDE │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Developer's Codebase │ │ +│ │ │ │ +│ │ package.json: │ │ +│ │ "@hubspot/ui-extensions": "^0.11.0" │ │ +│ │ │ │ +│ │ MyExtension.tsx: │ │ +│ │ import { Button, Card, Text } from '@hubspot/ui-extensions'; │ │ +│ │ import { hubspot } from '@hubspot/ui-extensions'; │ │ +│ │ │ │ +│ │ export function MyExtension({ context }) { │ │ +│ │ return ( │ │ +│ │ │ │ +│ │ Hello {context.user.name} │ │ +│ │ │ │ +│ │ │ │ +│ │ ); │ │ +│ │ } │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Developer provides: React code, component composition, business logic │ +│ Developer uses: Platform's component library (required or recommended) │ +│ Developer may NOT: Use arbitrary HTML/CSS (platform-dependent) │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Key Characteristics**: +- Developer writes actual code (usually React/TypeScript) +- Platform provides component library (may be required or optional) +- Code runs in platform's sandboxed environment +- Often paired with JS SDK for host interactions +- More flexibility than JSON, but still constrained to SDK + +**Variants**: +| Variant | BYO Components? | Example | +|---------|-----------------|---------| +| **Strict** | No - SDK only | HubSpot UI Extensions | +| **Recommended** | Yes, but SDK preferred | Canva Apps | +| **Flexible** | Yes - any React | Some Zendesk apps | + +--- + +## Type 3: Iframe + +**Pattern**: Developer provides full web app at a URL → Platform embeds in iframe + +**Examples**: Front Plugins, Intercom Apps, legacy integrations + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLATFORM SIDE │ +│ │ +│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │ +│ │ User │ │ Platform UI │ │ +│ │ Opens │───▶│ │ │ +│ │ Extension │ │ ┌────────────────────────────────────────────┐ │ │ +│ └─────────────┘ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ │ ▲ │ │ +│ │ │ postMessage │ │ +│ │ ▼ │ │ +│ │ ┌────────────────────────────────────────────┐ │ │ +│ │ │ Optional: JS SDK (loaded in iframe) │ │ │ +│ │ │ window.parent.postMessage(...) │ │ │ +│ │ │ or SDK wrapper: Front.send('...') │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ └──────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ + ▲ + │ HTTP (HTML/JS/CSS) + │ +┌────────────────────────────┴────────────────────────────────────────────────┐ +│ DEVELOPER SIDE │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Developer's Hosted Web Application │ │ +│ │ │ │ +│ │ - Any framework: React, Vue, Svelte, vanilla JS, etc. │ │ +│ │ - Any styling: Tailwind, Bootstrap, custom CSS │ │ +│ │ - Full control over rendering │ │ +│ │ │ │ +│ │ Optional: Load platform's JS SDK for host interaction │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Developer provides: Full web app (HTML, CSS, JS), hosting │ +│ Developer controls: Everything about rendering and behavior │ +│ Platform provides: Iframe container, optional SDK for communication │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Key Characteristics**: +- Maximum flexibility for developer +- Platform has minimal control over UI +- Often uses postMessage for communication +- May or may not have a JS SDK +- Developer responsible for styling consistency +- Security via iframe sandbox attributes + +--- + +## Type 4: Embedded SDK + +**Pattern**: Developer embeds platform's SDK into their own application + +**Examples**: Stripe Elements, Typeform Embed, Calendly, Analytics SDKs + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ DEVELOPER'S APPLICATION │ +│ (The developer IS the platform here) │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Developer's Web App │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │

My Checkout Page

│ │ +│ │ │ │ +│ │ │ │ +│ │ ┌────────────────────────────────────────────────────────┐ │ │ +│ │ │
│ │ │ +│ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ +│ │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ │ +│ │ │ │ │ Card Number │ │ Expiry │ │ │ │ │ +│ │ │ │ │ 4242 4242 4242 │ │ 12/25 │ │ │ │ │ +│ │ │ │ └──────────────────┘ └──────────────────┘ │ │ │ │ +│ │ │ │ ┌──────────────────┐ │ │ │ │ +│ │ │ │ │ CVC │ [Pay $99.00] │ │ │ │ +│ │ │ │ │ 123 │ │ │ │ │ +│ │ │ │ └──────────────────┘ │ │ │ │ +│ │ │ └──────────────────────────────────────────────────┘ │ │ │ +│ │ │
│ │ │ +│ │ │ (Stripe Elements - platform-rendered, secure) │ │ │ +│ │ └────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │
My app footer
│ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Developer provides: Host application, mount point, configuration │ +│ Platform provides: SDK that renders secure/compliant UI components │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + │ SDK loaded from + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLATFORM SIDE │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Platform's Embeddable SDK (e.g., Stripe.js) │ │ +│ │ │ │ +│ │ - Renders UI components in developer's page │ │ +│ │ - Handles sensitive data (PCI compliance for payments) │ │ +│ │ - Provides JS API for developer interaction │ │ +│ │ - May use iframes internally for security isolation │ │ +│ │ │ │ +│ │ Developer calls: │ │ +│ │ stripe.confirmPayment() │ │ +│ │ stripe.elements.create('card', options) │ │ +│ │ element.on('change', callback) │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Key Characteristics**: +- **Inverted relationship**: Developer's app is the host, platform provides embedded component +- Platform maintains control over sensitive rendering (e.g., payment fields) +- Developer integrates via JS SDK with mount points +- Often for compliance/security (PCI, authentication) +- Examples: Stripe Elements, PayPal Buttons, Plaid Link, Auth0 Lock + +**Note**: This is the "reverse" of the other types - here the developer is building the platform/app, and embedding someone else's UI component. + +--- + +## Cross-Cutting: JavaScript SDK Interaction + +Many extension types include a JS SDK for interacting with the host platform: + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ JS SDK INTERACTION PATTERN │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Platform Host Window │ │ +│ │ │ │ +│ │ window.platformSDK = { │ │ +│ │ │ │ +│ │ // Context │ │ +│ │ context: { │ │ +│ │ user: { id, name, email }, │ │ +│ │ record: { id, type, properties }, │ │ +│ │ locale: 'en-US' │ │ +│ │ }, │ │ +│ │ │ │ +│ │ // UI Actions │ │ +│ │ ui: { │ │ +│ │ showToast(message, type), │ │ +│ │ openModal(config), │ │ +│ │ closePanel() │ │ +│ │ }, │ │ +│ │ │ │ +│ │ // Data Actions │ │ +│ │ data: { │ │ +│ │ createRecord(type, data), │ │ +│ │ updateRecord(id, data), │ │ +│ │ query(type, filters) │ │ +│ │ }, │ │ +│ │ │ │ +│ │ // Events │ │ +│ │ on(event, callback), │ │ +│ │ off(event, callback) │ │ +│ │ }; │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Examples: │ +│ - Miro: window.miro.board.createShape(...) │ +│ - Front: Front.on('conversation', callback) │ +│ - Figma: figma.currentPage.selection │ +│ - Canva: canva.design.addNativeElement(...) │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**JS SDK should document**: +- Global object name (`window.miro`, `window.Front`, etc.) +- Available namespaces (ui, data, context, etc.) +- Method signatures and return types +- Event types and payloads +- Async patterns (Promises, callbacks) + +--- + +## Summary Table + +| Type | Who Renders? | Developer Provides | BYO Styling? | JS SDK? | +|------|--------------|-------------------|--------------|---------| +| **JSON Response** | Platform | JSON payloads | No | Rarely | +| **Coded Components** | Platform (from dev code) | React code + SDK components | Limited | Often | +| **Iframe** | Developer | Full web app | Yes | Optional | +| **Embedded SDK** | Platform (in dev's app) | Mount point + config | Limited | Required | diff --git a/specs/fenestra/TASKS.md b/specs/fenestra/TASKS.md new file mode 100644 index 0000000..01966c3 --- /dev/null +++ b/specs/fenestra/TASKS.md @@ -0,0 +1,97 @@ +# Fenestra Spec Development Tasks + +## Current Focus: Define the 4 Extension Types + +### The Four Types + +| Type | Description | Platform Provides | Developer Provides | +|------|-------------|-------------------|-------------------| +| **JSON Response** | Platform-sanctioned JSON payloads to API endpoints, renders pre-built components | Endpoint, schema, component renderer | JSON conforming to schema | +| **Coded Components** | SDK/UI Kit React components, sometimes BYO allowed | Component library, build tooling | React code using SDK | +| **Iframe** | Any HTML/JS/CSS at a URL | Iframe container, sometimes postMessage API | Full web application | +| **Embedded SDK** | ??? (needs clarification) | ??? | ??? | + +### Cross-cutting: JavaScript SDK + +When platforms expose a JS object to interact with host UI (e.g., `window.miro`, `window.Front`). + +--- + +## Tasks + +### Phase 1: Diagrams for Each Type +- [ ] Create diagram: JSON Response type (render flow) +- [ ] Create diagram: Coded Components type (render flow) +- [ ] Create diagram: Iframe type (render flow) +- [ ] Create diagram: Embedded SDK type (render flow) +- [ ] Create diagram: JS SDK interaction pattern + +### Phase 2: Map Real Ecosystems +- [ ] Google Workspace Apps → JSON Response +- [ ] Asana → JSON Response +- [ ] Gorgias → JSON Response +- [ ] HubSpot Timeline Events → JSON Response +- [ ] Pipedrive Extensions → JSON Response +- [ ] Salesforce LWC → Coded Components +- [ ] HubSpot UI Extensions → Coded Components +- [ ] Zendesk → Coded Components +- [ ] Canva SDK Apps → Coded Components +- [ ] (Identify iframe examples) +- [ ] (Identify embedded SDK examples) + +### Phase 3: Update Spec Schema +- [ ] Add `extensionType` enum to spec +- [ ] Define JSON Response schema details +- [ ] Define Coded Components schema details +- [ ] Define Iframe schema details +- [ ] Define Embedded SDK schema details +- [ ] Add JS SDK exposure schema + +### Phase 4: Create Example Documents +- [ ] Example: JSON Response platform +- [ ] Example: Coded Components platform +- [ ] Example: Iframe platform +- [ ] Example: Hybrid platform (multiple types) + +--- + +## Questions to Clarify + +1. **Embedded SDK/Options** - Can you give an example of this type? Is this like Stripe.js or analytics SDKs that get embedded in the dev's own app? + +2. **Hybrid platforms** - Some platforms offer multiple types (e.g., HubSpot has both JSON Timeline Events AND Coded UI Extensions). Should the spec handle this per-extension-point? + +--- + +## Ecosystem Research List + +### JSON Response Type +- Google Workspace Add-ons (Cards) +- Asana App Components +- Gorgias +- HubSpot Timeline Events (legacy) +- Pipedrive Extensions +- Slack Block Kit +- Microsoft Adaptive Cards +- Zoom Apps + +### Coded Components Type +- Salesforce Lightning Web Components +- HubSpot UI Extensions +- Zendesk Apps Framework +- Canva Apps SDK +- Shopify App Bridge + Polaris + +### Iframe Type +- Front Plugins +- Intercom Messenger Apps +- Many older integrations + +### Embedded SDK Type +- (Examples needed) + +### JS SDK Flavor (cross-cutting) +- Miro Web SDK (`miro` global) +- Front SDK (`Front` global) +- Canva SDK +- Figma Plugin API From 17415028af04794bdd1eaba1a880dbf5d2c9903b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Dec 2025 05:13:40 +0000 Subject: [PATCH 03/22] Add ecosystem mapping for 20+ platforms Researched and documented platforms across all 4 extension types: JSON Response (6 platforms): - Google Workspace, Asana, Gorgias, Pipedrive, Slack Block Kit, MS Adaptive Cards Coded Components (6 platforms): - HubSpot, Salesforce LWC, Canva, Shopify, Monday.com, Zendesk Iframe (6 platforms): - Front, Zendesk, Freshdesk, Intercom, Salesforce Canvas, Figma Embedded SDK (6 platforms): - Stripe Elements, Plaid Link, PayPal, Auth0, Calendly, Typeform Key findings documented: - BYO component policies vary significantly - Hybrid platforms support multiple types per extension point - JS SDK patterns are cross-cutting across all types - 10s timeout is common for JSON Response endpoints Files: - ECOSYSTEM-MAPPING.md - Detailed breakdown of each platform - TASKS.md - Updated with completed research tasks --- specs/fenestra/ECOSYSTEM-MAPPING.md | 541 ++++++++++++++++++++++++++++ specs/fenestra/TASKS.md | 134 ++++--- 2 files changed, 617 insertions(+), 58 deletions(-) create mode 100644 specs/fenestra/ECOSYSTEM-MAPPING.md diff --git a/specs/fenestra/ECOSYSTEM-MAPPING.md b/specs/fenestra/ECOSYSTEM-MAPPING.md new file mode 100644 index 0000000..0444b37 --- /dev/null +++ b/specs/fenestra/ECOSYSTEM-MAPPING.md @@ -0,0 +1,541 @@ +# Fenestra Ecosystem Mapping + +This document maps real-world platforms to the 4 extension types defined in the Fenestra specification. + +--- + +## Type 1: JSON Response + +Platform renders pre-built components from JSON payloads returned by developer's endpoint. + +| Platform | JSON Format | Components | Timeout | JS SDK | Docs | +|----------|-------------|------------|---------|--------|------| +| **Google Workspace** | `google.apps.card.v1` | 15+ widgets | Not specified | No (server-side) | [Link](https://developers.google.com/workspace/add-ons/concepts/card-interfaces) | +| **Asana** | OpenAPI-based | Modal Forms, Lookups, Widgets | 10s | No | [Link](https://developers.asana.com/docs/app-components) | +| **Gorgias** | Custom JSON | 5+ element types | ~10s | No | [Link](https://developers.gorgias.com/docs/create-integrations-and-widgets-programmatically) | +| **Pipedrive** | JSON Schema | Panels, Modals | 10s | Optional (for custom UI) | [Link](https://pipedrive.readme.io/docs/app-extensions-json-panels) | +| **Slack Block Kit** | Custom JSON | 8 blocks, 10+ elements | Not specified | No | [Link](https://docs.slack.dev/block-kit/) | +| **MS Adaptive Cards** | Platform-agnostic JSON | 25+ elements | Varies | Yes (rendering) | [Link](https://adaptivecards.io/) | + +### Detailed Breakdown + +#### Google Workspace Add-ons +```yaml +platform: Google Workspace +type: jsonResponse +schema: + format: google.apps.card.v1 + version: draft-07 + encoding: UTF-8 +endpoint: + method: POST + contextProvided: + - commonEventObject + - authorizationEventObject + - hostAppContext (gmail/drive/calendar) +components: + - TextParagraph + - TextInput + - Button / ButtonList + - SelectionInput (max 100 items) + - DateTimePicker + - DecoratedText + - Divider + - Grid + - Image / Icon +limits: + maxWidgets: 100 +``` + +#### Slack Block Kit +```yaml +platform: Slack +type: jsonResponse +schema: + format: custom + structure: Array of blocks with type field +endpoint: + method: POST + encoding: application/x-www-form-urlencoded + payloadTypes: + - block_actions + - view_submission + - view_closed + - shortcut +components: + blocks: + - section + - header + - actions + - input + - context + - divider + - rich_text + - image + - file + elements: + - button + - select / multi_select + - text_input + - datepicker / timepicker + - checkboxes / radio_buttons + - overflow +limits: + blocksPerMessage: 50 + blocksPerModal: 100 +``` + +#### Microsoft Adaptive Cards +```yaml +platform: Microsoft Teams / Outlook / Windows +type: jsonResponse +schema: + format: AdaptiveCard + version: "1.5" # Teams, 1.2 for mobile + platformAgnostic: true +components: + elements: + - TextBlock + - RichTextBlock + - Image + - Media + - Container + - ColumnSet / Column + - FactSet + - Table (v1.5+) + inputs: + - Input.Text + - Input.Number + - Input.Date + - Input.Time + - Input.Toggle + - Input.ChoiceSet + actions: + - Action.OpenUrl + - Action.Submit + - Action.ShowCard + - Action.ToggleVisibility + - Action.Execute +jsSdk: + package: "@microsoft/adaptivecards" + purpose: Client-side rendering +``` + +--- + +## Type 2: Coded Components + +Developer writes code (typically React) using platform's UI Kit. Code runs in platform's runtime. + +| Platform | SDK Package | Framework | BYO Allowed? | Host API | Docs | +|----------|-------------|-----------|--------------|----------|------| +| **HubSpot** | `@hubspot/ui-extensions` | React | No | SDK imports | [Link](https://developers.hubspot.com/docs/platform/ui-extensions-sdk) | +| **Salesforce LWC** | `lwc`, `lightning-base-components` | LWC (Web Components) | Restricted | `lightning/*` imports | [Link](https://developer.salesforce.com/docs/platform/lwc/overview) | +| **Canva** | `@canva/app-ui-kit` | React 19 | Yes (constrained) | `@canva/platform` | [Link](https://www.canva.dev/docs/apps/app-ui-kit/) | +| **Shopify** | CDN (Web Components) | Web Components | Discouraged | `shopify` global | [Link](https://shopify.dev/docs/api/app-bridge) | +| **Monday.com** | `@vibe/core`, `monday-sdk-js` | Agnostic (React rec.) | Yes | `mondaySDK` | [Link](https://developer.monday.com/apps/docs/vibe-design-system) | + +### Detailed Breakdown + +#### HubSpot UI Extensions +```yaml +platform: HubSpot +type: codedComponents +sdk: + package: "@hubspot/ui-extensions" + framework: React + runtime: Sandboxed iframe +componentRequirement: + level: required + byoAllowed: false + rationale: "Sandboxed iframe prevents DOM access" +components: + standard: + - Button, ButtonRow + - Text, Heading + - Input, TextArea, Select + - Card, Tile, Flex, Box + - Modal, Panel + - Table, DescriptionList + - Alert, Badge, Tag + - LoadingSpinner, ProgressBar + crmData: + package: "@hubspot/ui-extensions/crm" + components: + - CrmAssociationTable + - CrmPropertyList + - CrmActionButton +hostApi: + methods: + - runServerlessFunction() + - actions from SDK +``` + +#### Salesforce Lightning Web Components +```yaml +platform: Salesforce +type: codedComponents +sdk: + package: lwc + componentLibrary: lightning-base-components + framework: LWC (Web Components based) +componentRequirement: + level: required + byoAllowed: restricted + constraints: + - No third-party web components with npm dependencies + - Can load JS libraries via Static Resources + - Must use lwc:dom="manual" for external DOM manipulation +components: + categories: + - Input components + - Navigation components + - Table and tree components + - Visual components + - Form components + - Button variants (base, neutral, brand, destructive, success) +hostApi: + pattern: ES6 module imports + namespaces: + - lightning/platformResourceLoader + - lightning/uiRecordApi + - lightning/navigation +``` + +#### Canva Apps SDK +```yaml +platform: Canva +type: codedComponents +sdk: + package: "@canva/app-ui-kit" + platformSdk: "@canva/platform" + framework: React 19 +componentRequirement: + level: recommended + byoAllowed: true + constraints: + - Must wrap in AppUiProvider + - Should use design tokens for consistency + - Public apps: strongly recommended for design guidelines + - Team apps: optional but better UX +components: + - Button, LinkButton + - Rows, Text, Title + - Select (with multi-select) + - AudioCard, ImageCard +designTokens: + formats: + - JavaScript variables + - CSS variables + - React props +``` + +--- + +## Type 3: Iframe + +Developer provides full web app at URL. Platform loads in iframe with optional SDK for communication. + +| Platform | SDK Package | Global Object | Communication | Docs | +|----------|-------------|---------------|---------------|------| +| **Front** | `@frontapp/plugin-sdk` | `Front` | Observable pattern | [Link](https://dev.frontapp.com/docs/plugin-overview) | +| **Zendesk** | `zendesk_app_framework_sdk` | `ZAFClient` | get/set/invoke | [Link](https://developer.zendesk.com/api-reference/apps/apps-core-api/client_api/) | +| **Freshdesk** | `fresh_client.js` | `app` → `client` | Promise-based | [Link](https://developers.freshworks.com/docs/app-sdk/v2.3/freshdesk/) | +| **Intercom** | `@intercom/messenger-js-sdk` | `Intercom` | HTTP POST + Sheets | [Link](https://developers.intercom.com/docs/canvas-kit) | +| **Salesforce Canvas** | Canvas SDK | `Sfdc.canvas` | Signed requests | [Link](https://developer.salesforce.com/docs/atlas.en-us.platform_connect.meta/platform_connect/canvas_framework_using_sdk.htm) | +| **Figma** | `@figma/plugin-typings` | `figma` | postMessage | [Link](https://developers.figma.com/docs/plugins/) | + +### Detailed Breakdown + +#### Front Plugins +```yaml +platform: Front +type: iframe +extensionPoints: + - sidebar + - composer +sdk: + package: "@frontapp/plugin-sdk" + cdn: "https://dl.frontapp.com/libs/frontjs.min.js" + globalObject: Front +communication: + pattern: Observable + contextTypes: + - noConversation + - singleConversation + - multiConversations + methods: + - Front.contextUpdates (Observable) + - context.listMessages() + - context.createDraft() + - context.fetchConversation() +styling: + control: full + platformRestrictions: none +``` + +#### Zendesk Apps +```yaml +platform: Zendesk +type: iframe +sdk: + package: zendesk_app_framework_sdk + cdn: "https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js" + globalObject: ZAFClient +communication: + init: ZAFClient.init() + methods: + - client.get(path) # Read framework data + - client.set(path, value) # Write framework data + - client.invoke(method) # Run framework methods + - client.request(options) # HTTP requests + - client.on(event, handler) # Event listeners +componentRequirement: + level: optional + componentLibrary: "@zendeskgarden/*" + byoAllowed: true +``` + +#### Figma Plugins +```yaml +platform: Figma +type: iframe +architecture: + mainThread: + - Accesses Figma scene + - No browser APIs + - Sandboxed + uiIframe: + - Accesses browser APIs + - No Figma scene access + - Full framework freedom +sdk: + package: "@figma/plugin-typings" + globalObject: figma + uiMethods: + - figma.showUI(html) + - figma.ui.show() / hide() / close() + - figma.ui.postMessage() +communication: + pattern: postMessage between main thread and UI +componentRequirement: + level: optional + byoAllowed: true + notes: "Community component libraries available" +``` + +--- + +## Type 4: Embedded SDK + +Platform provides SDK that developer embeds in their own application. Platform renders secure UI components. + +| Platform | SDK Package | Global Object | Purpose | Theming | Docs | +|----------|-------------|---------------|---------|---------|------| +| **Stripe Elements** | `@stripe/stripe-js` | `Stripe` | Payments | Appearance API | [Link](https://docs.stripe.com/payments/elements) | +| **Plaid Link** | `react-plaid-link` | `Plaid` | Bank linking | Dashboard config | [Link](https://plaid.com/docs/link/web/) | +| **PayPal Buttons** | CDN only | `paypal` | Payments | Style options | [Link](https://developer.paypal.com/sdk/js/reference/) | +| **Auth0 Lock** | `auth0-lock` | `Auth0Lock` | Authentication | Theme options | [Link](https://auth0.com/docs/libraries/lock) | +| **Calendly** | CDN only | `Calendly` | Scheduling | Color customization | [Link](https://help.calendly.com/hc/en-us/articles/31618265722775) | +| **Typeform** | `@typeform/embed` | `tf` | Forms | Size/behavior | [Link](https://www.typeform.com/developers/embed/) | + +### Detailed Breakdown + +#### Stripe Elements +```yaml +platform: Stripe +type: embeddedSdk +purpose: PCI-compliant payment collection +sdk: + package: "@stripe/stripe-js" + reactPackage: "@stripe/react-stripe-js" + cdn: "https://js.stripe.com/v3/" # Must load from CDN + globalObject: Stripe +methods: + - loadStripe(publishableKey) + - stripe.elements(options) + - elements.create(type, options) + - element.mount(selector) + - stripe.confirmPayment(options) +communication: + pattern: callbacks + promises + events: + - element.on('change', handler) + - element.on('ready', handler) + - element.on('focus', handler) +theming: + system: Appearance API + prebuiltThemes: + - default + - stripe + - night + - flat + variables: + - colorPrimary + - colorBackground + - fontFamily + - borderRadius + rules: CSS-like selectors +``` + +#### Plaid Link +```yaml +platform: Plaid +type: embeddedSdk +purpose: Bank account linking +sdk: + package: react-plaid-link + cdn: "https://cdn.plaid.com/link/v2/stable/link-initialize.js" + globalObject: Plaid +methods: + - Plaid.create(config) + - handler.open() + - handler.exit() + - handler.destroy() +communication: + pattern: callbacks + events: + - onSuccess(public_token, metadata) + - onExit(err, metadata) + - onEvent(eventName, metadata) + eventTypes: + - OPEN + - TRANSITION_VIEW + - ERROR + - EXIT + - HANDOFF +theming: + location: Dashboard + options: + - Color schemes + - Text strings + - Overlay customization +``` + +#### Typeform Embed +```yaml +platform: Typeform +type: embeddedSdk +purpose: Embeddable forms and surveys +sdk: + package: "@typeform/embed" + reactPackage: "@typeform/embed-react" + cdn: "https://embed.typeform.com/next/embed.js" + globalObject: tf +embedTypes: + - createWidget() # Inline + - createPopup() # Modal + - createSlider() # Slide-in + - createSidetab() # Side button +methods: + - Returns { open, close, toggle, refresh } +communication: + pattern: callbacks + events: + - onReady({ formId, isClosed }) + - onStarted({ formId, responseId }) + - onQuestionChanged({ formId, ref }) + - onHeightChanged({ formId, ref, height }) + - onSubmit({ formId, responseId }) +theming: + options: + - width / height (CSS units) + - hideHeaders + - autoClose (ms) + - autoResize + sidetab: + - Full color/dimension customization +``` + +--- + +## Cross-Cutting: JavaScript SDK Patterns + +Many platforms expose a global object for host interaction: + +| Platform | Global Object | Namespaces | Async Pattern | +|----------|---------------|------------|---------------| +| Miro | `miro` | `miro.board`, `miro.ui` | Promises | +| Figma | `figma` | `figma.ui`, `figma.viewport`, `figma.clientStorage` | Sync + postMessage | +| Front | `Front` | `Front.contextUpdates` | Observable | +| Zendesk | `ZAFClient` | `client.get/set/invoke` | Promises | +| Canva | (imported) | `@canva/platform` | Imports | +| HubSpot | (imported) | `@hubspot/ui-extensions` | Imports | +| Stripe | `Stripe` | `stripe.elements` | Promises | +| PayPal | `paypal` | `paypal.Buttons`, `paypal.CardFields` | Callbacks | + +### Common SDK Capabilities + +```yaml +jsSdkCapabilities: + context: + description: "Access current state/environment" + examples: + - user info (id, name, email) + - current record/object + - locale/timezone + - permissions/scopes + + uiActions: + description: "Trigger platform UI elements" + examples: + - showToast(message) + - openModal(config) + - resize(dimensions) + - closePanel() + + dataActions: + description: "CRUD operations on platform data" + examples: + - createRecord(type, data) + - updateRecord(id, data) + - query(type, filters) + - deleteRecord(id) + + events: + description: "Subscribe to platform events" + patterns: + - sdk.on(event, callback) + - sdk.off(event, callback) + - Observable streams +``` + +--- + +## Hybrid Platforms + +Some platforms support multiple extension types: + +| Platform | Types Supported | Notes | +|----------|-----------------|-------| +| **Pipedrive** | JSON + Iframe | JSON for simple panels, iframe for custom UI | +| **HubSpot** | JSON (Timeline) + Coded | Timeline Events = JSON, UI Extensions = React | +| **Salesforce** | LWC + Canvas (iframe) | LWC for Lightning, Canvas for legacy/external | +| **Zendesk** | Coded + Iframe | Can use Garden components or full custom UI | +| **Intercom** | JSON (Canvas Kit) + Iframe (Sheets) | Canvas Kit for Messenger cards, Sheets for complex UI | + +--- + +## Summary by Extension Type + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ EXTENSION TYPE DISTRIBUTION │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ JSON RESPONSE CODED COMPONENTS IFRAME EMBEDDED │ +│ ────────────── ───────────────── ────── ──────── │ +│ • Google Workspace • HubSpot UI Ext • Front • Stripe │ +│ • Asana • Salesforce LWC • Zendesk • Plaid │ +│ • Gorgias • Canva • Freshdesk • PayPal │ +│ • Pipedrive (panels) • Shopify • Intercom • Auth0 │ +│ • Slack Block Kit • Monday.com • Figma • Calendly │ +│ • Adaptive Cards • Zendesk Garden • Salesforce • Typeform │ +│ Canvas │ +│ │ +│ ════════════════════════════════════════════════════════════════════════ │ +│ Platform renders Platform runs Developer app Platform │ +│ from JSON developer code in iframe in dev's │ +│ app │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` diff --git a/specs/fenestra/TASKS.md b/specs/fenestra/TASKS.md index 01966c3..408716f 100644 --- a/specs/fenestra/TASKS.md +++ b/specs/fenestra/TASKS.md @@ -9,35 +9,50 @@ | **JSON Response** | Platform-sanctioned JSON payloads to API endpoints, renders pre-built components | Endpoint, schema, component renderer | JSON conforming to schema | | **Coded Components** | SDK/UI Kit React components, sometimes BYO allowed | Component library, build tooling | React code using SDK | | **Iframe** | Any HTML/JS/CSS at a URL | Iframe container, sometimes postMessage API | Full web application | -| **Embedded SDK** | ??? (needs clarification) | ??? | ??? | +| **Embedded SDK** | Platform SDK embedded in developer's app for secure/compliant UI | SDK that renders in dev's page | Mount point, configuration, host app | ### Cross-cutting: JavaScript SDK -When platforms expose a JS object to interact with host UI (e.g., `window.miro`, `window.Front`). +When platforms expose a JS object to interact with host UI (e.g., `window.miro`, `window.Front`, `window.Stripe`). --- ## Tasks ### Phase 1: Diagrams for Each Type -- [ ] Create diagram: JSON Response type (render flow) -- [ ] Create diagram: Coded Components type (render flow) -- [ ] Create diagram: Iframe type (render flow) -- [ ] Create diagram: Embedded SDK type (render flow) -- [ ] Create diagram: JS SDK interaction pattern +- [x] Create diagram: JSON Response type (render flow) +- [x] Create diagram: Coded Components type (render flow) +- [x] Create diagram: Iframe type (render flow) +- [x] Create diagram: Embedded SDK type (render flow) +- [x] Create diagram: JS SDK interaction pattern + +**Output**: [DIAGRAMS.md](./DIAGRAMS.md) ### Phase 2: Map Real Ecosystems -- [ ] Google Workspace Apps → JSON Response -- [ ] Asana → JSON Response -- [ ] Gorgias → JSON Response -- [ ] HubSpot Timeline Events → JSON Response -- [ ] Pipedrive Extensions → JSON Response -- [ ] Salesforce LWC → Coded Components -- [ ] HubSpot UI Extensions → Coded Components -- [ ] Zendesk → Coded Components -- [ ] Canva SDK Apps → Coded Components -- [ ] (Identify iframe examples) -- [ ] (Identify embedded SDK examples) +- [x] Google Workspace Apps → JSON Response +- [x] Asana → JSON Response +- [x] Gorgias → JSON Response +- [x] Pipedrive Extensions → JSON Response (hybrid) +- [x] Slack Block Kit → JSON Response +- [x] Microsoft Adaptive Cards → JSON Response +- [x] Salesforce LWC → Coded Components +- [x] HubSpot UI Extensions → Coded Components +- [x] Zendesk → Coded Components / Iframe (hybrid) +- [x] Canva SDK Apps → Coded Components +- [x] Shopify App Bridge → Coded Components +- [x] Monday.com → Coded Components +- [x] Front → Iframe +- [x] Figma → Iframe +- [x] Freshdesk → Iframe +- [x] Intercom → Iframe +- [x] Stripe Elements → Embedded SDK +- [x] Plaid Link → Embedded SDK +- [x] PayPal Buttons → Embedded SDK +- [x] Auth0 Lock → Embedded SDK +- [x] Calendly → Embedded SDK +- [x] Typeform → Embedded SDK + +**Output**: [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md) ### Phase 3: Update Spec Schema - [ ] Add `extensionType` enum to spec @@ -48,50 +63,53 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - [ ] Add JS SDK exposure schema ### Phase 4: Create Example Documents -- [ ] Example: JSON Response platform -- [ ] Example: Coded Components platform -- [ ] Example: Iframe platform -- [ ] Example: Hybrid platform (multiple types) +- [ ] Example: JSON Response platform (Slack Block Kit) +- [ ] Example: Coded Components platform (already have HubSpot) +- [ ] Example: Iframe platform (Front) +- [ ] Example: Embedded SDK platform (Stripe) +- [ ] Example: Hybrid platform (Pipedrive or Zendesk) --- -## Questions to Clarify +## Key Findings from Research + +### JSON Response Platforms +- Typically 10s timeout for endpoint responses +- No client-side JS SDK needed (purely server-side) +- Schema validation enforced by platform +- Limited customization (only predefined components) + +### Coded Components Platforms +- React is dominant framework +- BYO policy varies: HubSpot (no), Canva (yes with constraints), Zendesk (yes) +- Often paired with JS SDK for host interaction +- Sandboxed execution (iframes or workers) + +### Iframe Platforms +- Maximum developer flexibility +- Platform provides SDK for communication (postMessage wrapper) +- Security via sandbox attributes and CSP +- Developer responsible for styling consistency + +### Embedded SDK Platforms +- Platform maintains control for security/compliance (PCI, etc.) +- Must load from platform CDN (cannot bundle) +- Theming options vary (Stripe: extensive, Plaid: limited) +- Callback/event-based communication + +### Hybrid Platforms +- Pipedrive: JSON panels + iframe custom UI +- HubSpot: JSON Timeline Events + Coded UI Extensions +- Zendesk: Garden components (recommended) + any framework +- Salesforce: LWC + Canvas (iframe) +- Intercom: Canvas Kit (JSON) + Sheets (iframe) -1. **Embedded SDK/Options** - Can you give an example of this type? Is this like Stripe.js or analytics SDKs that get embedded in the dev's own app? +--- -2. **Hybrid platforms** - Some platforms offer multiple types (e.g., HubSpot has both JSON Timeline Events AND Coded UI Extensions). Should the spec handle this per-extension-point? +## Questions Resolved ---- +1. ~~**Embedded SDK/Options** - What is this type?~~ + **Answer**: Platform SDK embedded in developer's own app for secure UI (e.g., Stripe Elements, Plaid Link) -## Ecosystem Research List - -### JSON Response Type -- Google Workspace Add-ons (Cards) -- Asana App Components -- Gorgias -- HubSpot Timeline Events (legacy) -- Pipedrive Extensions -- Slack Block Kit -- Microsoft Adaptive Cards -- Zoom Apps - -### Coded Components Type -- Salesforce Lightning Web Components -- HubSpot UI Extensions -- Zendesk Apps Framework -- Canva Apps SDK -- Shopify App Bridge + Polaris - -### Iframe Type -- Front Plugins -- Intercom Messenger Apps -- Many older integrations - -### Embedded SDK Type -- (Examples needed) - -### JS SDK Flavor (cross-cutting) -- Miro Web SDK (`miro` global) -- Front SDK (`Front` global) -- Canva SDK -- Figma Plugin API +2. **Hybrid platforms** - How to handle? + **Answer**: Model at extension-point level. Each extension point can have a different type. From 8fae126bf976698c132364ade7545822eab86f78 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Dec 2025 05:15:28 +0000 Subject: [PATCH 04/22] Add extension type schemas to Fenestra spec Added 4 extension type configurations to the spec: 1. JsonResponseConfig - For platforms like Slack Block Kit, Google Workspace - Schema format and validation - Endpoint configuration (timeout, auth, context) - Interactivity patterns (callbacks, payload types) 2. CodedComponentsConfig - For platforms like HubSpot, Salesforce LWC - SDK reference and framework - Runtime environment (sandbox, worker, direct) - Host interaction via JS SDK 3. IframeConfig - For platforms like Front, Zendesk, Figma - Sandbox attributes and CSP - Size constraints - Communication via JS SDK 4. EmbeddedSdkConfig - For platforms like Stripe, Plaid, PayPal - SDK package/CDN details - Mount pattern - Theming capabilities - Event-based communication Also added JsSdkConfig as cross-cutting schema for: - Global object name (window.miro, window.Front, etc.) - Initialization pattern - Namespace structure - Capabilities (context, UI actions, data, events) ExtensionPoint now requires extensionType field to specify which pattern the extension point uses. --- specs/fenestra/fenestra-spec.yaml | 371 ++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) diff --git a/specs/fenestra/fenestra-spec.yaml b/specs/fenestra/fenestra-spec.yaml index 25603e8..066b7fb 100644 --- a/specs/fenestra/fenestra-spec.yaml +++ b/specs/fenestra/fenestra-spec.yaml @@ -783,6 +783,7 @@ components: - id - name - type + - extensionType properties: id: type: string @@ -807,6 +808,28 @@ components: - embedded description: Type of extension point + extensionType: + type: string + enum: + - jsonResponse + - codedComponents + - iframe + - embeddedSdk + description: | + How the developer provides UI for this extension point: + - jsonResponse: Developer returns JSON from endpoint, platform renders + - codedComponents: Developer writes code using platform SDK/UI Kit + - iframe: Developer provides full web app at URL + - embeddedSdk: Platform SDK embedded in developer's app + + extensionTypeConfig: + oneOf: + - $ref: '#/components/schemas/JsonResponseConfig' + - $ref: '#/components/schemas/CodedComponentsConfig' + - $ref: '#/components/schemas/IframeConfig' + - $ref: '#/components/schemas/EmbeddedSdkConfig' + description: Configuration specific to the extension type + description: type: string @@ -920,3 +943,351 @@ components: number: NumberInput boolean: Checkbox date: DatePicker + + # ========================================================================= + # EXTENSION TYPE CONFIGURATIONS + # ========================================================================= + + JsonResponseConfig: + type: object + description: | + Configuration for JSON Response extension type. + Developer returns JSON from endpoint, platform renders pre-built components. + + Examples: Slack Block Kit, Google Workspace Add-ons, Asana App Components + properties: + schema: + type: object + description: JSON Schema definition for valid responses + properties: + format: + type: string + description: Schema format identifier + examples: + - "google.apps.card.v1" + - "slack.blocks" + - "adaptive-cards" + - "custom" + + version: + type: string + description: Schema version + + schemaUrl: + type: string + format: uri + description: URL to full JSON Schema definition + + encoding: + type: string + default: "UTF-8" + + endpoint: + type: object + description: How the platform calls the developer's endpoint + properties: + method: + type: string + enum: [GET, POST] + default: POST + + contentType: + type: string + default: "application/json" + + timeout: + type: integer + description: Request timeout in seconds + default: 10 + + authentication: + type: string + enum: + - none + - oauth + - jwt + - signedRequest + - apiKey + description: How requests are authenticated + + contextProvided: + type: array + items: + type: string + description: Context data sent with each request + examples: + - user + - record + - locale + - permissions + + interactivity: + type: object + description: How user interactions are handled + properties: + callbackUrl: + type: boolean + description: Whether platform POSTs interactions to callback URL + + payloadTypes: + type: array + items: + type: string + description: Types of interaction payloads + examples: + - block_actions + - view_submission + - form_submit + + CodedComponentsConfig: + type: object + description: | + Configuration for Coded Components extension type. + Developer writes code using platform's SDK/UI Kit. + + Examples: HubSpot UI Extensions, Salesforce LWC, Canva Apps SDK + properties: + sdk: + type: string + description: Reference to SDK in the sdks object + + framework: + type: string + enum: + - react + - vue + - lwc + - webComponents + - agnostic + description: Required or primary framework + + runtime: + type: object + description: How developer code is executed + properties: + type: + type: string + enum: + - sandboxedIframe + - webWorker + - directExecution + description: Execution environment + + bundling: + type: string + enum: + - platformBuild + - developerBuild + - cdn + description: How code is bundled and deployed + + hostInteraction: + $ref: '#/components/schemas/JsSdkConfig' + + IframeConfig: + type: object + description: | + Configuration for Iframe extension type. + Developer provides full web app at URL, platform loads in iframe. + + Examples: Front Plugins, Zendesk Apps, Figma Plugins + properties: + sandboxAttributes: + type: array + items: + type: string + description: iframe sandbox attribute values + examples: + - allow-scripts + - allow-forms + - allow-same-origin + - allow-popups + + cspRequirements: + type: string + description: Required Content Security Policy + + sizeConstraints: + type: object + properties: + minWidth: + type: integer + maxWidth: + type: integer + minHeight: + type: integer + maxHeight: + type: integer + resizable: + type: boolean + description: Whether iframe can be resized dynamically + + communication: + $ref: '#/components/schemas/JsSdkConfig' + + EmbeddedSdkConfig: + type: object + description: | + Configuration for Embedded SDK extension type. + Platform SDK is embedded in developer's own application. + + Examples: Stripe Elements, Plaid Link, PayPal Buttons + properties: + sdk: + type: object + description: SDK package details + properties: + package: + type: string + description: npm/CDN package name + + cdn: + type: string + format: uri + description: CDN URL (often required for security) + + cdnRequired: + type: boolean + description: Whether SDK must be loaded from CDN (cannot bundle) + default: false + + mountPattern: + type: string + enum: + - domSelector + - reactComponent + - webComponent + - function + description: How SDK components are mounted + + theming: + type: object + description: Styling/theming capabilities + properties: + system: + type: string + description: Theming system name + examples: + - "Appearance API" + - "Theme options" + - "CSS variables" + + prebuiltThemes: + type: array + items: + type: string + description: Available pre-built themes + + customizable: + type: boolean + description: Whether theming is customizable + + variables: + type: array + items: + type: string + description: Customizable theme variables + + communication: + type: object + properties: + pattern: + type: string + enum: + - callbacks + - events + - promises + - observables + description: Primary async communication pattern + + events: + type: array + items: + type: string + description: Events the SDK can emit + + # ========================================================================= + # JAVASCRIPT SDK CONFIGURATION + # ========================================================================= + + JsSdkConfig: + type: object + description: | + Configuration for JavaScript SDK that enables host interaction. + Cross-cutting concern that applies to multiple extension types. + properties: + globalObject: + type: string + description: Global window object name + examples: + - miro + - Front + - ZAFClient + - figma + - Stripe + + package: + type: string + description: npm package name (if applicable) + + cdn: + type: string + format: uri + description: CDN script URL + + initialization: + type: object + properties: + method: + type: string + description: How SDK is initialized + examples: + - "auto" + - "ZAFClient.init()" + - "loadStripe(key)" + + async: + type: boolean + description: Whether initialization is async + + namespaces: + type: object + description: SDK namespace structure + additionalProperties: + type: object + properties: + description: + type: string + methods: + type: array + items: + type: string + + capabilities: + type: object + description: What the SDK can do + properties: + context: + type: boolean + description: Can access current context/state + + uiActions: + type: boolean + description: Can trigger platform UI (toasts, modals) + + dataActions: + type: boolean + description: Can perform CRUD on platform data + + events: + type: boolean + description: Can subscribe to platform events + + asyncPattern: + type: string + enum: + - promises + - callbacks + - observables + - sync + description: Primary async pattern used From 2f9d0799ce6f43bdc3b06874d9dad44d446e62b1 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Dec 2025 02:52:34 +0000 Subject: [PATCH 05/22] Add Agent UI (5th extension type) for MCP Apps - Add AgentUIConfig and AgentUITemplate schemas to fenestra-spec.yaml - Create MCP Apps example document (mcp-apps.fenestra.yaml) - Add Agent UI render flow diagram to DIAGRAMS.md - Update TASKS.md to reflect 5 extension types (was 4) - Mark Phase 3 schema tasks as complete Agent UI represents the MCP Apps pattern where AI agents drive UI through pre-declared templates (forms, confirmations, progress) with custom iframe fallback for complex interactions. --- specs/fenestra/DIAGRAMS.md | 116 +++- specs/fenestra/TASKS.md | 31 +- .../fenestra/examples/mcp-apps.fenestra.yaml | 633 ++++++++++++++++++ specs/fenestra/fenestra-spec.yaml | 170 +++++ 4 files changed, 940 insertions(+), 10 deletions(-) create mode 100644 specs/fenestra/examples/mcp-apps.fenestra.yaml diff --git a/specs/fenestra/DIAGRAMS.md b/specs/fenestra/DIAGRAMS.md index 611f939..1593cdf 100644 --- a/specs/fenestra/DIAGRAMS.md +++ b/specs/fenestra/DIAGRAMS.md @@ -1,6 +1,6 @@ # Fenestra Extension Types - Diagrams -This document illustrates the 4 broad extension types and how rendering flows from developer-provided assets to user-visible UI. +This document illustrates the 5 broad extension types and how rendering flows from developer-provided assets to user-visible UI. --- @@ -382,6 +382,119 @@ Many extension types include a JS SDK for interacting with the host platform: --- +## Type 5: Agent UI + +**Pattern**: AI agent drives UI through pre-declared templates + custom iframe fallback + +**Examples**: MCP Apps hosts, AI assistant sidebars, LLM-powered interfaces + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLATFORM/HOST SIDE │ +│ │ +│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │ +│ │ AI Agent │ │ Host Application │ │ +│ │ (Server) │───▶│ │ │ +│ │ │ │ ┌────────────────────────────────────────────┐ │ │ +│ └─────────────┘ │ │ Template Renderer │ │ │ +│ │ │ │ │ │ │ +│ │ │ │ Agent invokes template: │ │ │ +│ │ │ │ ┌────────────────────────────────────┐ │ │ │ +│ │ │ │ │ { │ │ │ │ +│ │ │ │ │ "template": "form", │ │ │ │ +│ │ │ │ │ "data": { │ │ │ │ +│ │ JSON-RPC │ │ │ "title": "Enter Details", │ │ │ │ +│ │ over MCP │ │ │ "schema": { ... } │ │ │ │ +│ ▼ │ │ │ } │ │ │ │ +│ ┌───────────┐ │ │ │ } │ │ │ │ +│ │ Template │ │ │ └────────────────────────────────────┘ │ │ │ +│ │ Request │──────│ │ │ │ │ │ +│ └───────────┘ │ │ ▼ │ │ │ +│ │ │ ┌────────────────────────────────────┐ │ │ │ +│ │ │ │ Pre-built Templates │ │ │ │ +│ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ │ +│ │ │ │ │ Form │ │Confirm││Result│ ... │ │ │ │ +│ │ │ │ └──────┘ └──────┘ └──────┘ │ │ │ │ +│ │ │ │ (JSON Forms, platform components) │ │ │ │ +│ │ │ └────────────────────────────────────┘ │ │ │ +│ │ │ │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ │ ┌────────────────────────────────────────────┐ │ │ +│ │ │ OR: Custom Iframe Fallback │ │ │ +│ │ │ │ │ │ +│ │ │ Agent opens custom UI when templates │ │ │ +│ │ │ aren't sufficient: │ │ │ +│ │ │ ┌──────────────────────────────────────┐ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ └──────────────────────────────────────┘ │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ │ ▲ │ │ +│ │ │ User interaction │ │ +│ │ ▼ │ │ +│ │ ┌────────────────────────────────────────────┐ │ │ +│ │ │ Event Flow Back to Agent │ │ │ +│ │ │ - Form submitted → agent receives data │ │ │ +│ │ │ - Confirmation → agent continues/stops │ │ │ +│ │ │ - Custom action → agent handles event │ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ └──────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ + ▲ + │ MCP Protocol + │ +┌────────────────────────────┴────────────────────────────────────────────────┐ +│ AGENT/MCP SERVER SIDE │ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ MCP Server with UI Capability │ │ +│ │ │ │ +│ │ Declares UI templates in manifest: │ │ +│ │ { │ │ +│ │ "templates": ["form", "confirmation", "progress", "result"], │ │ +│ │ "customUIAllowed": true │ │ +│ │ } │ │ +│ │ │ │ +│ │ During tool execution: │ │ +│ │ 1. Agent decides UI is needed │ │ +│ │ 2. Invokes template: showUI("form", { schema, data }) │ │ +│ │ 3. Waits for user response │ │ +│ │ 4. Continues processing with user input │ │ +│ │ │ │ +│ │ Or for complex UI: │ │ +│ │ 1. Opens custom iframe: openCustomUI("https://...") │ │ +│ │ 2. Communicates via JSON-RPC in iframe │ │ +│ │ 3. Receives events and responds │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Agent provides: Template invocations, custom iframe URL (optional) │ +│ Agent does NOT provide: Template rendering logic (host handles that) │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Key Characteristics**: +- AI agent drives the UI programmatically +- Pre-declared templates for common patterns (forms, confirmations, progress) +- Custom iframe escape hatch for complex interactions +- JSON-RPC communication over MCP protocol +- JSON Forms used for structured input collection +- Agent can chain multiple UI interactions + +**Comparison to Other Types**: +| Aspect | Agent UI | JSON Response | Iframe | +|--------|----------|---------------|--------| +| Who decides what UI? | AI Agent | Developer endpoint | Developer app | +| Pre-declared templates? | Yes | Yes | No | +| Custom UI? | Via iframe fallback | No | Primary mode | +| Interaction pattern | Agent-driven loop | Request-response | User-driven | + +--- + ## Summary Table | Type | Who Renders? | Developer Provides | BYO Styling? | JS SDK? | @@ -390,3 +503,4 @@ Many extension types include a JS SDK for interacting with the host platform: | **Coded Components** | Platform (from dev code) | React code + SDK components | Limited | Often | | **Iframe** | Developer | Full web app | Yes | Optional | | **Embedded SDK** | Platform (in dev's app) | Mount point + config | Limited | Required | +| **Agent UI** | Platform (from agent invocations) | Template data + optional iframe | Via iframe only | Required (MCP) | diff --git a/specs/fenestra/TASKS.md b/specs/fenestra/TASKS.md index 408716f..55da15f 100644 --- a/specs/fenestra/TASKS.md +++ b/specs/fenestra/TASKS.md @@ -1,8 +1,8 @@ # Fenestra Spec Development Tasks -## Current Focus: Define the 4 Extension Types +## Current Focus: Define the 5 Extension Types -### The Four Types +### The Five Types | Type | Description | Platform Provides | Developer Provides | |------|-------------|-------------------|-------------------| @@ -10,6 +10,7 @@ | **Coded Components** | SDK/UI Kit React components, sometimes BYO allowed | Component library, build tooling | React code using SDK | | **Iframe** | Any HTML/JS/CSS at a URL | Iframe container, sometimes postMessage API | Full web application | | **Embedded SDK** | Platform SDK embedded in developer's app for secure/compliant UI | SDK that renders in dev's page | Mount point, configuration, host app | +| **Agent UI** | AI agent-driven UI with predeclared templates + custom iframe fallback | Template renderer, communication protocol | Template invocations, optional custom iframe | ### Cross-cutting: JavaScript SDK @@ -25,6 +26,7 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - [x] Create diagram: Iframe type (render flow) - [x] Create diagram: Embedded SDK type (render flow) - [x] Create diagram: JS SDK interaction pattern +- [x] Create diagram: Agent UI type (render flow) **Output**: [DIAGRAMS.md](./DIAGRAMS.md) @@ -55,19 +57,21 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, **Output**: [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md) ### Phase 3: Update Spec Schema -- [ ] Add `extensionType` enum to spec -- [ ] Define JSON Response schema details -- [ ] Define Coded Components schema details -- [ ] Define Iframe schema details -- [ ] Define Embedded SDK schema details -- [ ] Add JS SDK exposure schema +- [x] Add `extensionType` enum to spec +- [x] Define JSON Response schema details +- [x] Define Coded Components schema details +- [x] Define Iframe schema details +- [x] Define Embedded SDK schema details +- [x] Add JS SDK exposure schema +- [x] Define Agent UI schema details (AgentUIConfig, AgentUITemplate) ### Phase 4: Create Example Documents - [ ] Example: JSON Response platform (Slack Block Kit) -- [ ] Example: Coded Components platform (already have HubSpot) +- [x] Example: Coded Components platform (HubSpot) - [ ] Example: Iframe platform (Front) - [ ] Example: Embedded SDK platform (Stripe) - [ ] Example: Hybrid platform (Pipedrive or Zendesk) +- [x] Example: Agent UI platform (MCP Apps) --- @@ -104,6 +108,15 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - Salesforce: LWC + Canvas (iframe) - Intercom: Canvas Kit (JSON) + Sheets (iframe) +### Agent UI Platforms (NEW) +- MCP Apps hosts: Pre-declared templates + custom iframe fallback +- Key characteristics: + - AI agent drives the UI through structured invocations + - Templates for common patterns (forms, confirmations, progress) + - Custom iframe escape hatch for complex interactions + - JSON-RPC communication protocol + - JSON Forms for structured input collection + --- ## Questions Resolved diff --git a/specs/fenestra/examples/mcp-apps.fenestra.yaml b/specs/fenestra/examples/mcp-apps.fenestra.yaml new file mode 100644 index 0000000..1ebd223 --- /dev/null +++ b/specs/fenestra/examples/mcp-apps.fenestra.yaml @@ -0,0 +1,633 @@ +# MCP Apps Host - Fenestra Example +# +# This example describes an MCP-compatible AI assistant host that implements +# the MCP Apps specification for agent-driven UI. +# +# MCP Apps enables AI agents to present UI to users through: +# 1. Pre-declared templates (forms, confirmations, progress, etc.) +# 2. Custom iframe fallback for complex UI needs +# +# Reference: https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/ + +fenestra: "0.1.0" + +info: + title: MCP Apps Host UI Ecosystem + version: "1.0.0" + description: | + Describes the UI capabilities of an MCP Apps-compatible host application. + + MCP Apps extends the Model Context Protocol to enable AI-driven UI through + a hybrid model of pre-declared templates and custom iframe fallback. + +platform: + name: MCP Apps Host + vendor: Model Context Protocol + documentation: https://modelcontextprotocol.io/docs + +# ============================================================================= +# COMPONENT CATALOG +# ============================================================================= + +componentCatalog: + categories: + templates: + name: Agent UI Templates + description: Pre-declared templates agents can invoke + components: + - FormTemplate + - ConfirmationTemplate + - ProgressTemplate + - ResultTemplate + - ErrorTemplate + - ListTemplate + - DetailTemplate + - MediaTemplate + + components: + FormTemplate: + name: Form Template + description: | + Structured form for collecting user input. + Rendered using JSON Forms from a JSON Schema definition. + category: templates + webStandardMapping: + htmlElement: form + ariaRole: form + semanticType: input + props: + type: object + properties: + title: + type: string + description: Form title + description: + type: string + description: Form description/instructions + schema: + type: object + description: JSON Schema defining form fields + uiSchema: + type: object + description: Optional JSON Forms UI Schema for layout + submitLabel: + type: string + default: Submit + cancelLabel: + type: string + default: Cancel + required: + - title + - schema + + ConfirmationTemplate: + name: Confirmation Template + description: Yes/No or custom action confirmation dialog + category: templates + webStandardMapping: + htmlElement: dialog + ariaRole: alertdialog + semanticType: feedback + props: + type: object + properties: + title: + type: string + message: + type: string + confirmLabel: + type: string + default: Confirm + cancelLabel: + type: string + default: Cancel + variant: + type: string + enum: [info, warning, danger] + default: info + required: + - title + - message + + ProgressTemplate: + name: Progress Template + description: Shows operation progress with optional status messages + category: templates + webStandardMapping: + htmlElement: progress + ariaRole: progressbar + semanticType: feedback + props: + type: object + properties: + title: + type: string + message: + type: string + progress: + type: number + minimum: 0 + maximum: 100 + description: Progress percentage (0-100), omit for indeterminate + steps: + type: array + items: + type: object + properties: + label: + type: string + status: + type: string + enum: [pending, active, completed, error] + required: + - title + + ResultTemplate: + name: Result Template + description: Displays operation result/outcome + category: templates + webStandardMapping: + htmlElement: article + ariaRole: status + semanticType: display + props: + type: object + properties: + title: + type: string + message: + type: string + variant: + type: string + enum: [success, warning, error, info] + default: success + data: + type: object + description: Structured result data to display + actions: + type: array + items: + type: object + properties: + label: + type: string + actionId: + type: string + required: + - title + + ErrorTemplate: + name: Error Template + description: Displays error information with optional retry + category: templates + webStandardMapping: + htmlElement: div + ariaRole: alert + semanticType: feedback + props: + type: object + properties: + title: + type: string + default: Something went wrong + message: + type: string + code: + type: string + description: Error code for debugging + retryable: + type: boolean + default: false + retryLabel: + type: string + default: Try Again + required: + - message + + ListTemplate: + name: List Template + description: Displays a list of items with optional selection + category: templates + webStandardMapping: + htmlElement: ul + ariaRole: listbox + semanticType: display + props: + type: object + properties: + title: + type: string + items: + type: array + items: + type: object + properties: + id: + type: string + title: + type: string + description: + type: string + icon: + type: string + metadata: + type: object + selectable: + type: boolean + default: false + multiSelect: + type: boolean + default: false + required: + - items + + DetailTemplate: + name: Detail Template + description: Shows detailed information about an entity + category: templates + webStandardMapping: + htmlElement: article + ariaRole: article + semanticType: display + props: + type: object + properties: + title: + type: string + subtitle: + type: string + sections: + type: array + items: + type: object + properties: + heading: + type: string + fields: + type: array + items: + type: object + properties: + label: + type: string + value: + type: string + type: + type: string + enum: [text, link, code, date, currency] + actions: + type: array + items: + type: object + properties: + label: + type: string + actionId: + type: string + variant: + type: string + enum: [primary, secondary, danger] + required: + - title + + MediaTemplate: + name: Media Template + description: Displays media content (images, videos, documents) + category: templates + webStandardMapping: + htmlElement: figure + ariaRole: img + semanticType: display + props: + type: object + properties: + title: + type: string + mediaType: + type: string + enum: [image, video, audio, document, embed] + src: + type: string + format: uri + alt: + type: string + caption: + type: string + required: + - mediaType + - src + +# ============================================================================= +# EXTENSION POINTS +# ============================================================================= + +extensionPoints: + - id: agent-sidebar + name: Agent Sidebar Panel + type: sidebar + extensionType: agentUI + description: | + Sidebar panel where AI agent displays interactive UI. + Agent invokes templates or opens custom iframe as needed. + extensionTypeConfig: + templates: + supported: + - form + - confirmation + - progress + - result + - error + - list + - detail + - media + definitions: + form: + name: Form Template + description: Collect structured user input + inputSchema: + type: object + properties: + title: + type: string + schema: + type: object + required: + - title + - schema + outputSchema: + type: object + properties: + submitted: + type: boolean + data: + type: object + rendering: + type: jsonForms + interactivity: + submitButton: true + cancelButton: true + events: + - submit + - cancel + - fieldChange + + confirmation: + name: Confirmation Template + description: Confirm user action + inputSchema: + type: object + properties: + title: + type: string + message: + type: string + required: + - title + - message + outputSchema: + type: object + properties: + confirmed: + type: boolean + rendering: + type: platform + component: ConfirmationDialog + interactivity: + submitButton: true + cancelButton: true + events: + - confirm + - cancel + + progress: + name: Progress Template + description: Show operation progress + inputSchema: + type: object + properties: + title: + type: string + progress: + type: number + outputSchema: + type: object + properties: + cancelled: + type: boolean + rendering: + type: platform + component: ProgressIndicator + interactivity: + submitButton: false + cancelButton: true + events: + - cancel + + customUI: + allowed: true + sandboxAttributes: + - allow-scripts + - allow-forms + sizeConstraints: + maxWidth: 400 + maxHeight: 600 + resizable: true + + communication: + protocol: jsonRpc + channels: + - templates + - customUI + - events + - actions + + agentCapabilities: + invokeTemplates: true + openCustomUI: true + receiveEvents: true + closeUI: true + chainInteractions: true + + constraints: + maxWidth: 400 + maxHeight: 800 + responsive: true + + context: + provides: + - conversation + - user + - recentMessages + actions: + - sendMessage + - executeToolCall + - requestPermission + + - id: agent-modal + name: Agent Modal Dialog + type: modal + extensionType: agentUI + description: | + Full-screen modal for complex agent interactions. + Supports all templates plus custom iframe. + extensionTypeConfig: + templates: + supported: + - form + - confirmation + - progress + - result + - error + - list + - detail + - media + customUI: + allowed: true + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + sizeConstraints: + maxWidth: 800 + maxHeight: 600 + resizable: false + communication: + protocol: jsonRpc + channels: + - templates + - customUI + - events + agentCapabilities: + invokeTemplates: true + openCustomUI: true + receiveEvents: true + closeUI: true + chainInteractions: true + + constraints: + maxWidth: 800 + maxHeight: 600 + responsive: true + + context: + provides: + - conversation + - user + - selectedContent + actions: + - sendMessage + - close + + - id: inline-card + name: Inline Card + type: card + extensionType: agentUI + description: | + Inline card within conversation for quick interactions. + Limited to simpler templates (no custom iframe). + extensionTypeConfig: + templates: + supported: + - result + - error + - list + customUI: + allowed: false + communication: + protocol: jsonRpc + channels: + - templates + - events + agentCapabilities: + invokeTemplates: true + openCustomUI: false + receiveEvents: true + closeUI: false + chainInteractions: false + + constraints: + maxWidth: 600 + maxHeight: 300 + responsive: true + + context: + provides: + - message + - toolCallId + actions: + - expandToModal + +# ============================================================================= +# POLICIES +# ============================================================================= + +policies: + componentRequirement: + level: required + scope: all + rationale: | + MCP Apps hosts require use of pre-declared templates to ensure + consistent, secure, and accessible UI across all agents. + + customComponents: + allowed: true + constraints: + - sandboxOnly + registrationRequired: false + approvalRequired: false + documentation: https://modelcontextprotocol.io/docs/mcp-apps/custom-ui + + publishing: + privateApps: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: false + notes: | + Private/development MCP servers have full flexibility. + + publicApps: + componentRequirement: recommended + customComponentsAllowed: true + reviewRequired: true + notes: | + Published MCP servers should prefer templates for consistency, + but can use custom UI when needed. + +# ============================================================================= +# RENDERING ENGINES +# ============================================================================= + +renderingEngines: + templates: + type: mcpApps + name: MCP Apps Template Renderer + description: | + Renders pre-declared templates based on MCP Apps specification. + Uses JSON Forms for form templates, platform components for others. + schemaSupport: + dataSchema: jsonSchema + uiSchema: mcpAppsTemplate + customRenderers: false + + forms: + type: jsonForms + name: JSON Forms Renderer + description: | + Renders form templates using JSON Forms specification. + Automatically generates UI from JSON Schema. + schemaSupport: + dataSchema: jsonSchema + uiSchema: jsonFormsUISchema + customRenderers: true + + customUI: + type: custom + name: Custom Iframe Renderer + description: | + Renders custom UI in sandboxed iframe for complex interactions. + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + cspPolicy: "default-src 'self'; script-src 'self'" diff --git a/specs/fenestra/fenestra-spec.yaml b/specs/fenestra/fenestra-spec.yaml index 066b7fb..744bc58 100644 --- a/specs/fenestra/fenestra-spec.yaml +++ b/specs/fenestra/fenestra-spec.yaml @@ -815,12 +815,14 @@ components: - codedComponents - iframe - embeddedSdk + - agentUI description: | How the developer provides UI for this extension point: - jsonResponse: Developer returns JSON from endpoint, platform renders - codedComponents: Developer writes code using platform SDK/UI Kit - iframe: Developer provides full web app at URL - embeddedSdk: Platform SDK embedded in developer's app + - agentUI: AI agent-driven UI with predeclared templates + custom iframe extensionTypeConfig: oneOf: @@ -828,6 +830,7 @@ components: - $ref: '#/components/schemas/CodedComponentsConfig' - $ref: '#/components/schemas/IframeConfig' - $ref: '#/components/schemas/EmbeddedSdkConfig' + - $ref: '#/components/schemas/AgentUIConfig' description: Configuration specific to the extension type description: @@ -1206,6 +1209,173 @@ components: type: string description: Events the SDK can emit + AgentUIConfig: + type: object + description: | + Configuration for Agent UI extension type. + AI agents drive UI through predeclared templates + custom iframe fallback. + + Based on the MCP Apps proposal - enables AI-driven UI through structured + templates while preserving escape hatch to full custom UI. + + Examples: MCP Apps hosts, AI assistant sidebars, LLM-powered interfaces + properties: + templates: + type: object + description: Pre-declared UI templates the agent can invoke + properties: + supported: + type: array + items: + type: string + description: Template types supported by the host + examples: + - form + - confirmation + - progress + - result + - error + - list + - detail + - media + + definitions: + type: object + description: Template definitions with their schemas + additionalProperties: + $ref: '#/components/schemas/AgentUITemplate' + + customUI: + type: object + description: Custom iframe fallback for complex UI needs + properties: + allowed: + type: boolean + description: Whether custom iframe UI is supported + default: true + + sandboxAttributes: + type: array + items: + type: string + description: iframe sandbox attributes for custom UI + + sizeConstraints: + type: object + properties: + maxWidth: + type: integer + maxHeight: + type: integer + resizable: + type: boolean + + communication: + type: object + description: How agent and UI communicate + properties: + protocol: + type: string + enum: + - jsonRpc + - postMessage + - mcp + description: Primary communication protocol + default: jsonRpc + + channels: + type: array + items: + type: string + description: Communication channels available + examples: + - templates + - customUI + - events + - actions + + agentCapabilities: + type: object + description: What the agent can do through the UI + properties: + invokeTemplates: + type: boolean + description: Can invoke pre-declared templates + default: true + + openCustomUI: + type: boolean + description: Can open custom iframe UI + default: true + + receiveEvents: + type: boolean + description: Can receive UI events (clicks, submissions) + default: true + + closeUI: + type: boolean + description: Can programmatically close UI + default: true + + chainInteractions: + type: boolean + description: Can chain multiple UI interactions + default: true + + AgentUITemplate: + type: object + description: Definition of a pre-declared agent UI template + properties: + name: + type: string + description: Template identifier + + description: + type: string + description: What this template is used for + + inputSchema: + type: object + description: JSON Schema for template input data + + outputSchema: + type: object + description: JSON Schema for template output (user response) + + rendering: + type: object + description: How the template is rendered + properties: + type: + type: string + enum: + - platform + - jsonForms + - custom + description: Rendering strategy + + component: + type: string + description: Platform component used for rendering + + interactivity: + type: object + properties: + submitButton: + type: boolean + description: Has a submit action + + cancelButton: + type: boolean + description: Has a cancel action + + events: + type: array + items: + type: string + description: Events this template can emit + # ========================================================================= # JAVASCRIPT SDK CONFIGURATION # ========================================================================= From 74ad7cacef86b767c8f71d4ed47cad17acf29ca0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Dec 2025 03:00:01 +0000 Subject: [PATCH 06/22] Add workflow/automation platforms to ecosystem mapping - Add Zapier Apps (JSON fields + Interfaces components) - Add Make.com (RPC-driven parameter system) - Add Power Automate (OpenAPI connectors + Adaptive Cards) - Add NetSuite (customization + SuiteScript + SPAs) Key insight: All workflow platforms rely heavily on JSON-driven schemas and maintain strict rendering control (no iframe mode). --- specs/fenestra/ECOSYSTEM-MAPPING.md | 222 +++++++++++++++++++++++++--- specs/fenestra/TASKS.md | 12 ++ 2 files changed, 214 insertions(+), 20 deletions(-) diff --git a/specs/fenestra/ECOSYSTEM-MAPPING.md b/specs/fenestra/ECOSYSTEM-MAPPING.md index 0444b37..f81ffc2 100644 --- a/specs/fenestra/ECOSYSTEM-MAPPING.md +++ b/specs/fenestra/ECOSYSTEM-MAPPING.md @@ -1,6 +1,6 @@ # Fenestra Ecosystem Mapping -This document maps real-world platforms to the 4 extension types defined in the Fenestra specification. +This document maps real-world platforms to the 5 extension types defined in the Fenestra specification. --- @@ -516,26 +516,208 @@ Some platforms support multiple extension types: --- +## Workflow & Automation Platforms + +Integration/automation platforms with their own UI extension models. + +| Platform | Types Supported | UI Definition | Developer Provides | Docs | +|----------|-----------------|---------------|-------------------|------| +| **Zapier** | JSON + Coded | Field defs + Interfaces | Field schemas, triggers | [Link](https://docs.zapier.com/) | +| **Make.com** | JSON (RPC) | Parameter specs | Module config, RPC endpoints | [Link](https://developers.make.com/) | +| **Power Automate** | JSON (OpenAPI + Adaptive Cards) | OpenAPI 2.0 + Card JSON | API spec, card definitions | [Link](https://learn.microsoft.com/en-us/connectors/) | +| **NetSuite** | JSON + Coded (SuiteScript + SPAs) | Point-click + SuiteScript API + JSX | Code or config | [Link](https://docs.oracle.com/en/cloud/saas/netsuite/) | + +### Detailed Breakdown + +#### Zapier Apps +```yaml +platform: Zapier +type: hybrid (jsonResponse + codedComponents) +approaches: + platformUI: + type: jsonResponse + description: "JSON field definitions for triggers/actions" + fieldTypes: + - text, email, url, password + - dropdown (static/dynamic) + - checkbox, radio, toggle + - date/datetime, code + dynamicFields: true (via hidden triggers) + + interfaces: + type: codedComponents + description: "No-code component builder for custom pages" + components: + - Form, Table, Kanban + - Button, Layout + - Media, Rich Text, Embed + +sdk: + package: "@zapier/platform-sdk" # Optional, for CLI + globalObject: none + jsSdk: false # Platform controls rendering + +constraints: + - Input forms optional for triggers, required for actions + - Dynamic fields limited in Platform UI (full support in CLI) + - Custom styling not allowed + - Interfaces components have predefined styling +``` + +#### Make.com (Integromat) +```yaml +platform: Make.com +type: jsonResponse +description: "RPC-driven parameter system for dynamic fields" + +uiDefinition: + format: Make parameter specification + fieldTypes: + - text (all text-based inputs) + - select (static or RPC-generated) + - search button (large datasets) + - checkbox, radio, file + +rpcSystem: + description: "Remote Procedure Calls for runtime field generation" + types: + dynamicOptions: "Generates dropdown/search options from API" + dynamicFields: "Fetches field definitions from server" + output: "Array of { label, value } objects" + nesting: true # RPCs can call other RPCs + +sdk: + package: none # REST/GraphQL to external services + globalObject: none + +constraints: + - No npm packages; must use external API calls + - Type conversion needed (Make uses "text" not "string") + - Cannot build custom React components or iframe UIs + - Field types limited to platform-supported types +``` + +#### Power Automate +```yaml +platform: Power Automate +type: hybrid (jsonResponse) +approaches: + customConnectors: + type: jsonResponse + description: "OpenAPI 2.0 based connector definitions" + format: OpenAPI 2.0 (Swagger) + inputTypes: + - All primitives (string, number, boolean, integer) + - Array/object structures + - Enums (dropdown options) + - File upload/download + maxFileSize: 1MB + authentication: API Key, OAuth, Basic + + adaptiveCards: + type: jsonResponse + description: "Platform-agnostic card format" + format: AdaptiveCard JSON + version: "1.5" # Teams, 1.2 for mobile + components: + - TextBlock, RichTextBlock + - Input.Text, Input.Number, Input.Date, Input.Time + - Input.Toggle, Input.ChoiceSet + - Container, ColumnSet, Table + - Button actions (OpenUrl, Submit, ShowCard) + +copilotStudio: + type: agentUI + description: "Ask with Adaptive Card nodes for AI interactions" + +sdk: + adaptiveCards: "@microsoft/adaptivecards" + purpose: Client-side card rendering + +constraints: + - Connectors limited to OpenAPI 2.0 format + - No custom code execution in connectors + - Adaptive Cards: restricted component set, no arbitrary HTML/CSS + - Security/compliance validation required for published connectors +``` + +#### NetSuite +```yaml +platform: NetSuite +type: hybrid (jsonResponse + codedComponents) +approaches: + customization: + type: jsonResponse + description: "Point-and-click form customization" + capabilities: + - Field visibility/organization + - Drag-and-drop UI + codeRequired: false + + suiteScript: + type: codedComponents + description: "Server-side UI component rendering" + framework: SuiteScript 2.x + module: N/ui/serverWidget + pageTypes: + - Form + - List + - Assistant + components: + - Button, TextField, Textarea + - Select (dropdown), Checkbox, Radio + - Date/datetime, Fields with custom formatting + - Sublist (data grid), Group/Tab organization + rendering: Server-side to HTML + + spas: + type: codedComponents + description: "Modern JSX-based Single Page Applications (2025.1+)" + framework: SuiteScript 2.1 + JSX + uiFramework: UIF (User Interface Framework) + components: + - Grids, buttons, inputs, modals + - Form handling, Layout components + moduleSystem: ESM (ECMAScript Modules) + tools: SuiteCloud Development Framework (SDF) + +sdk: + suiteScript: "N/ui/serverWidget, N/record" + spas: "@netsuite/uif" + devTools: SuiteCloud Developer Assistant (AI-powered) + +constraints: + - Customization limited to form layout/visibility + - SuiteScript: Server-side rendering, client interaction via Client Scripts + - SPAs require SuiteScript 2.1 (not backward compatible with 2.0) + - Module system migration required (ESM for SPAs vs RequireJS for older code) +``` + +--- + ## Summary by Extension Type ``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ EXTENSION TYPE DISTRIBUTION │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ JSON RESPONSE CODED COMPONENTS IFRAME EMBEDDED │ -│ ────────────── ───────────────── ────── ──────── │ -│ • Google Workspace • HubSpot UI Ext • Front • Stripe │ -│ • Asana • Salesforce LWC • Zendesk • Plaid │ -│ • Gorgias • Canva • Freshdesk • PayPal │ -│ • Pipedrive (panels) • Shopify • Intercom • Auth0 │ -│ • Slack Block Kit • Monday.com • Figma • Calendly │ -│ • Adaptive Cards • Zendesk Garden • Salesforce • Typeform │ -│ Canvas │ -│ │ -│ ════════════════════════════════════════════════════════════════════════ │ -│ Platform renders Platform runs Developer app Platform │ -│ from JSON developer code in iframe in dev's │ -│ app │ -└─────────────────────────────────────────────────────────────────────────────┘ +┌───────────────────────────────────────────────────────────────────────────────────────┐ +│ EXTENSION TYPE DISTRIBUTION │ +├───────────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ JSON RESPONSE CODED COMPONENTS IFRAME EMBEDDED SDK AGENT UI │ +│ ────────────── ───────────────── ────── ──────────── ──────── │ +│ • Google Workspace • HubSpot UI Ext • Front • Stripe • MCP Apps │ +│ • Asana • Salesforce LWC • Zendesk • Plaid • Copilot │ +│ • Gorgias • Canva • Freshdesk • PayPal Studio │ +│ • Pipedrive • Shopify • Intercom • Auth0 │ +│ • Slack Block Kit • Monday.com • Figma • Calendly │ +│ • Adaptive Cards • Zendesk Garden • Salesforce • Typeform │ +│ • Zapier (fields) • Zapier Interfaces Canvas │ +│ • Make.com (RPC) • NetSuite SPAs │ +│ • Power Automate • NetSuite Script │ +│ • NetSuite Custom │ +│ │ +│ ════════════════════════════════════════════════════════════════════════════════ │ +│ Platform renders Platform runs Developer app Platform SDK AI agent │ +│ from JSON developer code in iframe in dev's app drives UI │ +│ │ +└───────────────────────────────────────────────────────────────────────────────────────┘ ``` diff --git a/specs/fenestra/TASKS.md b/specs/fenestra/TASKS.md index 55da15f..eb9b64e 100644 --- a/specs/fenestra/TASKS.md +++ b/specs/fenestra/TASKS.md @@ -53,6 +53,10 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - [x] Auth0 Lock → Embedded SDK - [x] Calendly → Embedded SDK - [x] Typeform → Embedded SDK +- [x] Zapier → JSON Response + Coded Components (hybrid) +- [x] Make.com → JSON Response (RPC-driven) +- [x] Power Automate → JSON Response (OpenAPI + Adaptive Cards) +- [x] NetSuite → JSON Response + Coded Components (hybrid) **Output**: [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md) @@ -117,6 +121,14 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - JSON-RPC communication protocol - JSON Forms for structured input collection +### Workflow/Automation Platforms (NEW) +- Zapier: JSON field definitions + Interfaces (no-code component builder) +- Make.com: RPC-driven parameter system (unique dynamic field pattern) +- Power Automate: OpenAPI 2.0 connectors + Adaptive Cards +- NetSuite: Point-click customization + SuiteScript + JSX SPAs (2025.1+) +- Key insight: All rely heavily on JSON-driven schemas +- No iframe mode: Unlike Figma/Front, these platforms maintain strict rendering control + --- ## Questions Resolved From 12733c02d5724af7caa94371cf8592ae4b6a39e6 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Dec 2025 03:04:22 +0000 Subject: [PATCH 07/22] Fix categorization: NetSuite is ERP, not workflow platform --- specs/fenestra/ECOSYSTEM-MAPPING.md | 9 +++++++++ specs/fenestra/TASKS.md | 16 +++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/specs/fenestra/ECOSYSTEM-MAPPING.md b/specs/fenestra/ECOSYSTEM-MAPPING.md index f81ffc2..a622669 100644 --- a/specs/fenestra/ECOSYSTEM-MAPPING.md +++ b/specs/fenestra/ECOSYSTEM-MAPPING.md @@ -525,6 +525,15 @@ Integration/automation platforms with their own UI extension models. | **Zapier** | JSON + Coded | Field defs + Interfaces | Field schemas, triggers | [Link](https://docs.zapier.com/) | | **Make.com** | JSON (RPC) | Parameter specs | Module config, RPC endpoints | [Link](https://developers.make.com/) | | **Power Automate** | JSON (OpenAPI + Adaptive Cards) | OpenAPI 2.0 + Card JSON | API spec, card definitions | [Link](https://learn.microsoft.com/en-us/connectors/) | + +--- + +## ERP Platforms + +Enterprise Resource Planning systems with UI customization capabilities. + +| Platform | Types Supported | UI Definition | Developer Provides | Docs | +|----------|-----------------|---------------|-------------------|------| | **NetSuite** | JSON + Coded (SuiteScript + SPAs) | Point-click + SuiteScript API + JSX | Code or config | [Link](https://docs.oracle.com/en/cloud/saas/netsuite/) | ### Detailed Breakdown diff --git a/specs/fenestra/TASKS.md b/specs/fenestra/TASKS.md index eb9b64e..bc2aa0f 100644 --- a/specs/fenestra/TASKS.md +++ b/specs/fenestra/TASKS.md @@ -53,10 +53,10 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - [x] Auth0 Lock → Embedded SDK - [x] Calendly → Embedded SDK - [x] Typeform → Embedded SDK -- [x] Zapier → JSON Response + Coded Components (hybrid) -- [x] Make.com → JSON Response (RPC-driven) -- [x] Power Automate → JSON Response (OpenAPI + Adaptive Cards) -- [x] NetSuite → JSON Response + Coded Components (hybrid) +- [x] Zapier → JSON Response + Coded Components (hybrid) [Workflow] +- [x] Make.com → JSON Response (RPC-driven) [Workflow] +- [x] Power Automate → JSON Response (OpenAPI + Adaptive Cards) [Workflow] +- [x] NetSuite → JSON Response + Coded Components (hybrid) [ERP] **Output**: [ECOSYSTEM-MAPPING.md](./ECOSYSTEM-MAPPING.md) @@ -125,10 +125,16 @@ When platforms expose a JS object to interact with host UI (e.g., `window.miro`, - Zapier: JSON field definitions + Interfaces (no-code component builder) - Make.com: RPC-driven parameter system (unique dynamic field pattern) - Power Automate: OpenAPI 2.0 connectors + Adaptive Cards -- NetSuite: Point-click customization + SuiteScript + JSX SPAs (2025.1+) - Key insight: All rely heavily on JSON-driven schemas - No iframe mode: Unlike Figma/Front, these platforms maintain strict rendering control +### ERP Platforms (NEW) +- NetSuite: Point-click customization + SuiteScript + JSX SPAs (2025.1+) +- Unique characteristics: + - Server-side UI rendering (SuiteScript 2.x) + - Modern JSX/ESM approach (SuiteScript 2.1 SPAs) + - AI-powered development assistant + --- ## Questions Resolved From c63d1b2840d9fad3a10ff76d76d648a46b466876 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Dec 2025 01:57:39 +0000 Subject: [PATCH 08/22] Add Use Cases and expand Relationship to Other Specs sections Use Cases added: 1. Visual Designer with Code Generation - generative design platform 2. Cross-Platform Portability - design once, generate for multiple targets 3. AI Agent Interoperability - MCP agents query UI capabilities 4. Frigg Module Integration - modules declare UI capabilities 5. Validation & Linting - pre-flight checks against platform constraints 6. Documentation Generation - auto-generate developer docs 7. Migration Assistance - port apps between platforms Also clarifies that Fenestra is a Platform Capabilities Spec, not an API spec, and can exist independently of OpenAPI documents. --- specs/fenestra/README.md | 219 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 213 insertions(+), 6 deletions(-) diff --git a/specs/fenestra/README.md b/specs/fenestra/README.md index 3220e0b..3e8ec41 100644 --- a/specs/fenestra/README.md +++ b/specs/fenestra/README.md @@ -31,12 +31,219 @@ The OAI has demonstrated success in standardizing API descriptions. Fenestra ext ## Relationship to Other Specifications -| Specification | Purpose | Fenestra Integration | -|--------------|---------|---------------------| -| **OpenAPI** | API description | Fenestra extends OpenAPI patterns for UI description | -| **Arazzo** | Workflow orchestration | Workflow steps can reference Fenestra UI for user interactions | -| **MCP Apps** | AI-driven UI resources | Fenestra components map to MCP App templates | -| **JSON Forms** | Schema-driven forms | Fenestra supports JSON Schema-based rendering | +Fenestra is **not an API specification** - it's a **Platform Capabilities Specification**. It describes UI ecosystems, not HTTP endpoints. + +### Spec Family Comparison + +| Specification | Describes | Example | +|---------------|-----------|---------| +| **OpenAPI** | REST API endpoints | `POST /contacts` returns `Contact` | +| **AsyncAPI** | Event-driven APIs | `order.created` event payload | +| **Arazzo** | Workflows across APIs | "Create contact, then send email" | +| **Fenestra** | UI extension ecosystems | "Platform has Button, Card, uses React SDK" | + +### Can Fenestra Exist Independently? + +**Yes.** A platform's UI ecosystem exists independently of its API: + +``` +┌─────────────────────────────────────────────────────┐ +│ HubSpot │ +├─────────────────────────────────────────────────────┤ +│ │ +│ OpenAPI Doc Fenestra Doc │ +│ ───────────── ──────────── │ +│ • GET /contacts • UI Extensions SDK │ +│ • POST /deals • CRM Cards │ +│ • OAuth flows • Component catalog │ +│ • Webhook schemas • BYO policy: No │ +│ │ +│ (How to call the API) (How to build UI) │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +### Relationship Models + +Fenestra can relate to OpenAPI in several ways: + +1. **Standalone** - Fenestra doc exists independently (most common) +2. **Companion** - Both specs describe the same platform side-by-side +3. **Cross-Reference** - OpenAPI operations reference Fenestra for UI responses +4. **Embedded** - `x-fenestra` extension embeds UI info in OpenAPI docs + +| Integration | Fenestra Relation | +|-------------|-------------------| +| **OpenAPI** | Companion spec; can cross-reference via `$ref` | +| **Arazzo** | Workflow steps can invoke Fenestra-described UI for user interactions | +| **MCP Apps** | Fenestra describes host UI capabilities for agent-driven interfaces | +| **JSON Forms** | Fenestra documents which platforms support JSON Schema-based rendering | + +--- + +## Use Cases + +Having Fenestra specs for each platform enables powerful tooling and workflows. + +### 1. Visual Designer with Code Generation + +Build a **generative design platform** where: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ VISUAL DESIGNER │ +│ │ +│ ┌─────────────┐ ┌─────────────────────────────────────────┐│ +│ │ Target: │ │ ││ +│ │ [HubSpot ▼] │ │ ┌─────────────────────────────────┐ ││ +│ └─────────────┘ │ │ Card │ ││ +│ │ │ ┌─────────────────────────────┐│ ││ +│ Components: │ │ │ Text: "Customer Info" ││ ││ +│ ┌─────────────┐ │ │ ├─────────────────────────────┤│ ││ +│ │ ☑ Button │ │ │ │ [Input: Email ] ││ ││ +│ │ ☑ Card │ │ │ │ [Select: Status ▼] ││ ││ +│ │ ☑ Input │ │ │ │ ││ ││ +│ │ ☑ Select │ │ │ │ [Save Button] ││ ││ +│ │ ☐ CustomDiv │←───│───│ └─────────────────────────────┘│ ││ +│ │ (blocked) │ │ └─────────────────────────────────┘ ││ +│ └─────────────┘ │ ││ +│ └─────────────────────────────────────────┘│ +│ Fenestra tells Canvas reflects platform constraints │ +│ designer what's │ +│ allowed │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ Generate +┌─────────────────────────────────────────────────────────────────┐ +│ // Generated HubSpot UI Extension │ +│ import { Card, Input, Select, Button } from '@hubspot/ui-ext'; │ +│ │ +│ export function CustomerCard({ context }) { │ +│ return ( │ +│ │ +│ Customer Info │ +│ │ +│ │ -│ + language: html + + select: + name: Select Menu + description: Dropdown menu styled to match Figma + category: input + sdkBinding: + sdk: figma-plugin-ds + export: select + webStandardMapping: + htmlElement: select + ariaRole: listbox + semanticType: input + examples: + - title: Select Menu + code: | +
+ +
+
+ language: html + + checkbox: + name: Checkbox + description: Checkbox styled to match Figma + category: input + sdkBinding: + sdk: figma-plugin-ds + export: checkbox + webStandardMapping: + htmlElement: input[type="checkbox"] + ariaRole: checkbox + semanticType: input + examples: + - title: Checkbox + code: | + + language: html + + switch: + name: Switch + description: Toggle switch styled to match Figma + category: input + sdkBinding: + sdk: figma-plugin-ds + export: switch + webStandardMapping: + htmlElement: input[type="checkbox"] + ariaRole: switch + semanticType: input + examples: + - title: Switch + code: | + + language: html + + section: + name: Section + description: Content section container + category: layout + sdkBinding: + sdk: figma-plugin-ds + export: section + webStandardMapping: + htmlElement: section + ariaRole: region + semanticType: container + examples: + - title: Section + code: | +
+
Section Title
+
+ Content goes here +
+
+ language: html + + disclosure: + name: Disclosure + description: Collapsible section with expand/collapse + category: layout + sdkBinding: + sdk: figma-plugin-ds + export: disclosure + webStandardMapping: + htmlElement: details + ariaRole: group + semanticType: container + examples: + - title: Disclosure + code: | +
+
+
+ Advanced Options +
+
+ Hidden content +
+
+ language: html + + widgetAutoLayout: + name: Widget AutoLayout + description: Auto layout container for on-canvas widgets + category: widget + sdkBinding: + sdk: figma-widget-api + export: AutoLayout + webStandardMapping: + htmlElement: div + semanticType: layout + examples: + - title: Widget AutoLayout + code: | + const { widget } = figma; + const { AutoLayout, Text } = widget; + + function Widget() { + return ( + + Hello World + + ); + } + language: jsx + + widgetText: + name: Widget Text + description: Text display for on-canvas widgets + category: widget + sdkBinding: + sdk: figma-widget-api + export: Text + webStandardMapping: + htmlElement: span + semanticType: display + examples: + - title: Widget Text + code: | + + Widget text content + + language: jsx + + widgetInput: + name: Widget Input + description: Text input field for on-canvas widgets + category: widget + sdkBinding: + sdk: figma-widget-api + export: Input + webStandardMapping: + htmlElement: input + semanticType: input + examples: + - title: Widget Input + code: | + const [value, setValue] = useSyncedState('text', ''); + return ( + setValue(e.characters)} + placeholder="Enter text" + /> + ); + language: jsx + +policies: + componentRequirement: + level: optional + scope: all + rationale: | + Figma provides no official component library. The community-maintained + figma-plugin-ds is popular but entirely optional. Developers have + complete freedom to build UIs with any HTML/CSS/JS approach. + + customComponents: + allowed: true + constraints: + - sandboxOnly + registrationRequired: false + approvalRequired: false + documentation: https://www.figma.com/plugin-docs/creating-ui/ + + publishing: + privateApps: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: false + notes: "Private plugins have complete freedom" + + publicApps: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: true + notes: "Community plugins undergo review for security and quality" + + marketplaceApps: + componentRequirement: optional + customComponentsAllowed: true + certificationRequired: false + notes: "All community plugins follow same review process" + + designGuidelines: + required: false + designSystem: "figma-plugin-ds (community)" + designSystemUrl: https://github.com/thomas-lowry/figma-plugin-ds + designTokensProvided: false + + security: + sandbox: true + sandboxDescription: | + All plugin UI runs in a sandboxed iframe. The main plugin code + runs in a separate JavaScript context with access to the Figma API + but no DOM access. Communication between contexts uses postMessage. + cspPolicy: "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src https:" + +extensionPoints: + - id: plugin-ui + name: Plugin UI + type: modal + extensionType: iframe + description: | + Sandboxed iframe UI that can be shown as a modal or panel. + Communicates with main plugin code via postMessage. + supportedComponents: + - all + constraints: + resizable: true + responsive: true + context: + provides: + - selection + - currentPage + - document + - user + actions: + - createNode + - modifyNode + - deleteNode + - showUI + - closePlugin + extensionTypeConfig: + sandboxAttributes: + - allow-scripts + - allow-forms + communication: + globalObject: "parent" + initialization: + method: "postMessage to parent" + async: true + asyncPattern: promises + capabilities: + context: true + uiActions: true + dataActions: true + events: true + + - id: widget-canvas + name: Canvas Widget (Figma) + type: canvas + extensionType: codedComponents + description: | + Interactive on-canvas widget that lives in the Figma document. + Uses a React-like declarative API with limited component set. + Available in Figma files (not FigJam). + supportedComponents: + - widgetAutoLayout + - widgetText + - widgetInput + - widgetFrame + constraints: + responsive: true + context: + provides: + - widgetNode + - syncedState + - document + actions: + - updateWidget + - openUI + extensionTypeConfig: + sdk: figma-widget-api + framework: react + runtime: + type: directExecution + bundling: platformBuild + + - id: figjam-widget + name: FigJam Widget + type: canvas + extensionType: codedComponents + description: | + Interactive widget for FigJam collaborative whiteboard. + Similar to Figma widgets but with FigJam-specific features. + Can include stickers, voting, and collaboration features. + supportedComponents: + - widgetAutoLayout + - widgetText + - widgetInput + - widgetFrame + constraints: + responsive: true + context: + provides: + - widgetNode + - syncedState + - figjamDocument + actions: + - updateWidget + - openUI + - createSticky + extensionTypeConfig: + sdk: figma-widget-api + framework: react + runtime: + type: directExecution + bundling: platformBuild + + - id: plugin-menu + name: Plugin Menu Command + type: contextMenu + extensionType: codedComponents + description: | + Command in the Figma plugins menu that executes code without showing UI. + Can optionally open UI after execution. + supportedComponents: [] + context: + provides: + - selection + - currentPage + - document + actions: + - createNode + - modifyNode + - showUI + +renderingEngines: + iframe-html: + type: custom + name: HTML + CSS in Iframe + description: | + Plugin UI is plain HTML/CSS/JavaScript rendered in a sandboxed iframe. + Developers can use figma-plugin-ds CSS library or custom styling. + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + cspPolicy: "default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" + + widget-declarative: + type: custom + name: Widget Declarative API + description: | + On-canvas widgets use a React-like declarative syntax with a limited + set of built-in components (AutoLayout, Text, Input, etc.) + sandboxing: + iframeSandbox: false + +architecture: + executionModel: dual-context + description: | + Figma plugins use a dual-context architecture: + + 1. Main Thread: Runs plugin code with access to Figma API (figma.*) + - No DOM access + - Can read/write document nodes + - Can trigger UI display + + 2. UI Thread: Sandboxed iframe with HTML/CSS/JS + - Full DOM access for rendering UI + - No direct Figma API access + - Communicates with main thread via postMessage + + This separation ensures security while allowing rich custom UIs. + + communication: + protocol: postMessage + description: | + Main thread and UI thread communicate via window.postMessage API. + + Main -> UI: figma.ui.postMessage(data) + UI -> Main: parent.postMessage({ pluginMessage: data }, '*') + + Main thread listens: figma.ui.onmessage = (msg) => { ... } + UI thread listens: window.onmessage = (event) => { ... } + +jsonFormsIntegration: + supported: true + rendererSet: custom + customRenderersAllowed: true + notes: | + Developers can integrate JSON Forms with custom renderers using + figma-plugin-ds or their own components in the UI iframe. + +mcpAppsIntegration: + supported: false + notes: | + Not currently integrated with MCP Apps specification, but the iframe + architecture could potentially support MCP Apps UI resources in the future. + +extensions: + compliance: + communityGuidelines: + url: https://www.figma.com/community/plugin-guidelines/ + description: | + Figma Community Guidelines govern what plugins can be published. + Key requirements: + - No malicious code or data harvesting + - Must respect user privacy + - Clear description of functionality + - Appropriate content only + - No trademark/copyright violations + + reviewProcess: + required: true + scope: public + description: | + All community plugins undergo review before publication: + 1. Automated security checks + 2. Manual review of code and functionality + 3. Testing for performance and stability + 4. Verification of description accuracy + timeline: "1-2 weeks typical review time" + + securityRequirements: + - name: Sandboxing + description: All UI must run in sandboxed iframe + required: true + - name: API Access + description: Only access Figma API from main thread + required: true + - name: Network Requests + description: Declare all network requests in manifest + required: true + - name: Data Privacy + description: No unauthorized data collection or transmission + required: true + + manifest: + file: manifest.json + description: | + Every plugin requires a manifest.json file defining: + - Plugin metadata (name, id, version) + - Main code file path + - UI file path (if using UI) + - Permissions and capabilities + - Menu commands + - Network access requirements + schema: + name: + type: string + required: true + id: + type: string + required: true + description: Unique plugin ID assigned by Figma + api: + type: string + required: true + description: Figma API version (e.g., "1.0.0") + main: + type: string + required: true + description: Path to main plugin code file + ui: + type: string + required: false + description: Path to UI HTML file + capabilities: + type: array + required: false + description: Special capabilities (e.g., "codegen", "inspect") + networkAccess: + type: object + required: false + description: Allowed network domains + + developmentTools: + - name: Figma Plugin API Typings + description: TypeScript definitions for Figma Plugin API + package: "@figma/plugin-typings" + + - name: Create Figma Plugin + description: CLI tool for scaffolding new plugins + package: "create-figma-plugin" + command: "npm init figma-plugin" + url: https://github.com/yuanqing/create-figma-plugin + + - name: Figma Plugin DS + description: Community design system matching Figma's UI + package: "figma-plugin-ds" + url: https://github.com/thomas-lowry/figma-plugin-ds + + - name: Hot Reload + description: Built-in hot reload during development + builtin: true + description: "Figma supports hot reload in development mode" diff --git a/specs/fenestra/examples/0.1.0/salesforce.fenestra.yaml b/specs/fenestra/examples/0.1.0/salesforce.fenestra.yaml new file mode 100644 index 0000000..9f7a952 --- /dev/null +++ b/specs/fenestra/examples/0.1.0/salesforce.fenestra.yaml @@ -0,0 +1,1118 @@ +# Fenestra Document: Salesforce Lightning Web Components (LWC) +# +# Salesforce LWC represents a component-based ecosystem with both required base +# components and the flexibility to create custom components following strict +# guidelines and security policies. + +fenestra: "0.1.0" + +info: + title: Salesforce Lightning Web Components Ecosystem + version: "1.0.0" + description: | + Salesforce Lightning Web Components (LWC) is a modern framework for building + enterprise applications on the Salesforce Platform using standard Web Components. + + LWC leverages core Web Components standards (Custom Elements, Shadow DOM, + Templates, and ES Modules) to deliver fast, standards-based components that + work seamlessly within Salesforce's Lightning Experience and Experience Cloud. + + Key characteristics: + - Built on Web Components standards + - Required use of Salesforce Lightning Design System (SLDS) for AppExchange apps + - Extensive base component library (lightning namespace) + - Strict security model with LockerService + - Governor limits enforce efficient code + - Mandatory security review for AppExchange publication + +platform: + name: Salesforce Platform + vendor: Salesforce, Inc. + documentation: https://developer.salesforce.com/docs/platform/lwc/overview + componentLibrary: https://developer.salesforce.com/docs/component-library + appMarketplace: https://appexchange.salesforce.com/ + designSystem: https://www.lightningdesignsystem.com/ + +sdks: + lightning-base-components: + name: Lightning Base Components + packageManager: salesforce + package: lightning/* + version: API 60.0 + documentation: https://developer.salesforce.com/docs/component-library/overview/components + description: | + Base components provided by Salesforce in the lightning namespace. + These components are automatically available in all LWC components. + exports: + # Action Components + lightning-button: + type: component + description: Standard button with multiple variants + category: action + lightning-button-icon: + type: component + description: Icon-only button + category: action + lightning-button-group: + type: component + description: Group of related buttons + category: action + lightning-button-menu: + type: component + description: Dropdown menu button + category: action + lightning-button-stateful: + type: component + description: Button with selected/unselected states + category: action + + # Input Components + lightning-input: + type: component + description: Input field supporting multiple types (text, number, email, etc.) + category: input + lightning-textarea: + type: component + description: Multi-line text input + category: input + lightning-combobox: + type: component + description: Dropdown selection with search + category: input + lightning-dual-listbox: + type: component + description: Dual list selection + category: input + lightning-checkbox-group: + type: component + description: Group of checkboxes + category: input + lightning-radio-group: + type: component + description: Radio button group + category: input + lightning-slider: + type: component + description: Range slider input + category: input + lightning-input-field: + type: component + description: Field-aware input for record forms + category: input + + # Display Components + lightning-card: + type: component + description: Container with header, body, and footer + category: display + lightning-accordion: + type: component + description: Collapsible sections + category: display + lightning-avatar: + type: component + description: User or entity avatar + category: display + lightning-badge: + type: component + description: Status or label badge + category: display + lightning-pill: + type: component + description: Removable tag or label + category: display + lightning-formatted-text: + type: component + description: Display formatted text + category: display + lightning-formatted-number: + type: component + description: Display formatted numbers + category: display + lightning-formatted-date-time: + type: component + description: Display formatted dates and times + category: display + lightning-formatted-email: + type: component + description: Display email with mailto link + category: display + lightning-formatted-phone: + type: component + description: Display phone with tel link + category: display + lightning-formatted-url: + type: component + description: Display formatted URL + category: display + lightning-icon: + type: component + description: Display SLDS icons + category: display + lightning-progress-indicator: + type: component + description: Step-based progress indicator + category: display + lightning-progress-bar: + type: component + description: Linear progress bar + category: display + lightning-spinner: + type: component + description: Loading spinner + category: display + + # Data Display Components + lightning-datatable: + type: component + description: Rich data table with sorting, inline editing + category: data + lightning-tree: + type: component + description: Hierarchical tree view + category: data + lightning-tree-grid: + type: component + description: Tree view with data table features + category: data + + # Layout Components + lightning-layout: + type: component + description: Grid-based layout container + category: layout + lightning-layout-item: + type: component + description: Item within lightning-layout + category: layout + lightning-tab: + type: component + description: Tab within tabset + category: layout + lightning-tabset: + type: component + description: Tabbed interface + category: layout + lightning-vertical-navigation: + type: component + description: Vertical navigation menu + category: layout + + # Record Components + lightning-record-form: + type: component + description: Automatic record create/edit/view form + category: record + lightning-record-edit-form: + type: component + description: Customizable record edit form + category: record + lightning-record-view-form: + type: component + description: Customizable record view form + category: record + lightning-output-field: + type: component + description: Display field value with formatting + category: record + + # Overlay Components + lightning-modal: + type: component + description: Modal dialog (API 58.0+) + category: overlay + since: "API 58.0" + + # Navigation + lightning-navigation: + type: component + description: Navigate to pages within Salesforce + category: navigation + + # Messaging + lightning-messages: + type: component + description: Display field-level error messages + category: messaging + + # Map + lightning-map: + type: component + description: Display map with markers + category: display + + lightning-ui-api: + name: Lightning UI API Modules + packageManager: salesforce + package: lightning/ui*Api + version: API 60.0 + documentation: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_ui_api + description: | + Wire adapters and functions for working with Salesforce data declaratively. + These modules provide reactive data access with automatic caching. + exports: + # Record APIs + getRecord: + type: wireAdapter + module: lightning/uiRecordApi + description: Get record data reactively + getRecords: + type: wireAdapter + module: lightning/uiRecordApi + description: Get multiple records + createRecord: + type: function + module: lightning/uiRecordApi + description: Create a new record + updateRecord: + type: function + module: lightning/uiRecordApi + description: Update existing record + deleteRecord: + type: function + module: lightning/uiRecordApi + description: Delete a record + getFieldValue: + type: function + module: lightning/uiRecordApi + description: Extract field value from record + getFieldDisplayValue: + type: function + module: lightning/uiRecordApi + description: Get formatted field value + + # List APIs + getListUi: + type: wireAdapter + module: lightning/uiListApi + description: Get list view data + + # Object APIs + getObjectInfo: + type: wireAdapter + module: lightning/uiObjectInfoApi + description: Get object metadata + getPicklistValues: + type: wireAdapter + module: lightning/uiObjectInfoApi + description: Get picklist values + getPicklistValuesByRecordType: + type: wireAdapter + module: lightning/uiObjectInfoApi + description: Get picklist values for record type + + lightning-platform: + name: Lightning Platform Modules + packageManager: salesforce + package: lightning/platform* + version: API 60.0 + documentation: https://developer.salesforce.com/docs/platform/lwc/guide + description: | + Platform services for navigation, messaging, and resource loading. + exports: + # Navigation + NavigationMixin: + type: mixin + module: lightning/navigation + description: Navigate to pages, records, and external URLs + category: navigation + + # Messaging + publish: + type: function + module: lightning/messageService + description: Publish Lightning Message Service message + category: messaging + subscribe: + type: function + module: lightning/messageService + description: Subscribe to Lightning Message Service channel + category: messaging + unsubscribe: + type: function + module: lightning/messageService + description: Unsubscribe from message channel + category: messaging + createMessageContext: + type: function + module: lightning/messageService + description: Create message context + category: messaging + + # Resource Loading + loadStyle: + type: function + module: lightning/platformResourceLoader + description: Load CSS from static resources + category: resource + loadScript: + type: function + module: lightning/platformResourceLoader + description: Load JavaScript from static resources + category: resource + + # Notifications + ShowToastEvent: + type: event + module: lightning/platformShowToastEvent + description: Display toast notification + category: messaging + + # Refresh + RefreshEvent: + type: event + module: lightning/refresh + description: Trigger standard refresh (API 59.0+) + category: event + since: "API 59.0" + + salesforce-lightning-design-system: + name: Salesforce Lightning Design System (SLDS) + packageManager: npm + package: "@salesforce-ux/design-system" + version: "^2.24.0" + repository: https://github.com/salesforce-ux/design-system + documentation: https://www.lightningdesignsystem.com/ + description: | + The design system for Salesforce Lightning. Provides CSS framework, + design tokens, icons, and design guidelines. Required for AppExchange apps. + exports: + # Design Tokens + design-tokens: + type: designTokens + description: SLDS design tokens for colors, spacing, typography + + # Icons + standard-icons: + type: iconSet + description: Standard object icons + utility-icons: + type: iconSet + description: Utility action icons + custom-icons: + type: iconSet + description: Custom app icons + action-icons: + type: iconSet + description: Action icons + doctype-icons: + type: iconSet + description: Document type icons + + # CSS Framework + slds-core: + type: css + description: Core SLDS CSS framework + +componentCatalog: + categories: + action: + name: Action + description: Buttons and actionable elements + components: + - lightning-button + - lightning-button-icon + - lightning-button-group + - lightning-button-menu + - lightning-button-stateful + + input: + name: Input + description: Form input components + components: + - lightning-input + - lightning-textarea + - lightning-combobox + - lightning-dual-listbox + - lightning-checkbox-group + - lightning-radio-group + - lightning-slider + - lightning-input-field + + display: + name: Display + description: Components for displaying content + components: + - lightning-card + - lightning-accordion + - lightning-avatar + - lightning-badge + - lightning-pill + - lightning-formatted-text + - lightning-formatted-number + - lightning-formatted-date-time + - lightning-icon + - lightning-progress-indicator + - lightning-progress-bar + - lightning-spinner + - lightning-map + + data: + name: Data Display + description: Complex data visualization components + components: + - lightning-datatable + - lightning-tree + - lightning-tree-grid + + layout: + name: Layout + description: Layout and structure components + components: + - lightning-layout + - lightning-layout-item + - lightning-tab + - lightning-tabset + - lightning-vertical-navigation + + record: + name: Record + description: Salesforce record management components + components: + - lightning-record-form + - lightning-record-edit-form + - lightning-record-view-form + - lightning-output-field + + overlay: + name: Overlay + description: Modal and overlay components + components: + - lightning-modal + + components: + lightning-button: + name: Lightning Button + description: | + Standard button component with support for multiple variants, icons, + and accessibility features. Automatically styled per SLDS guidelines. + category: action + sdkBinding: + sdk: lightning-base-components + export: lightning-button + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + label: + type: string + description: Button label text + variant: + type: string + enum: [base, neutral, brand, brand-outline, destructive, destructive-text, inverse, success] + default: neutral + description: Visual variant of the button + type: + type: string + enum: [button, submit, reset] + default: button + disabled: + type: boolean + default: false + icon-name: + type: string + description: SLDS icon name + icon-position: + type: string + enum: [left, right] + default: left + variants: + - base + - neutral + - brand + - brand-outline + - destructive + - destructive-text + - inverse + - success + accessibility: + keyboardSupport: true + screenReaderSupport: true + ariaSupport: true + + lightning-datatable: + name: Lightning Datatable + description: | + Advanced data table with sorting, inline editing, row selection, + and custom cell rendering. Supports large datasets with virtualization. + category: data + sdkBinding: + sdk: lightning-base-components + export: lightning-datatable + webStandardMapping: + htmlElement: table + ariaRole: grid + semanticType: data + props: + data: + type: array + description: Array of data objects + required: true + columns: + type: array + description: Column definitions with type, label, and field name + required: true + key-field: + type: string + description: Unique identifier field for rows + required: true + sorted-by: + type: string + description: Field name to sort by + sorted-direction: + type: string + enum: [asc, desc] + show-row-number-column: + type: boolean + default: false + hide-checkbox-column: + type: boolean + default: false + events: + rowselection: + description: Fired when row selection changes + rowaction: + description: Fired when row action is clicked + sort: + description: Fired when column sort is requested + accessibility: + keyboardSupport: true + screenReaderSupport: true + ariaSupport: true + + lightning-card: + name: Lightning Card + description: | + Container component with optional header, body, and footer sections. + Follows SLDS card design patterns. + category: display + sdkBinding: + sdk: lightning-base-components + export: lightning-card + webStandardMapping: + htmlElement: article + ariaRole: article + semanticType: container + props: + title: + type: string + description: Card title in header + icon-name: + type: string + description: SLDS icon name for header + slots: + default: + description: Card body content + required: false + actions: + description: Actions in card header + required: false + footer: + description: Card footer content + required: false + accessibility: + keyboardSupport: true + screenReaderSupport: true + + lightning-record-form: + name: Lightning Record Form + description: | + Automatically generates a form for creating, editing, or viewing + records with field-level security, validation, and layout support. + category: record + sdkBinding: + sdk: lightning-base-components + export: lightning-record-form + webStandardMapping: + htmlElement: form + ariaRole: form + semanticType: form + props: + object-api-name: + type: string + description: API name of the Salesforce object + required: true + record-id: + type: string + description: Record ID (omit for create mode) + fields: + type: array + description: Array of field API names to display + mode: + type: string + enum: [view, edit, readonly] + default: edit + layout-type: + type: string + enum: [Compact, Full] + columns: + type: number + enum: [1, 2] + events: + success: + description: Fired when record is successfully saved + error: + description: Fired when save operation fails + submit: + description: Fired when form is submitted + accessibility: + keyboardSupport: true + screenReaderSupport: true + ariaSupport: true + + lightning-modal: + name: Lightning Modal + description: | + Modal dialog component for confirmations and focused tasks. + Available in API 58.0+. Extends LightningModal base class. + category: overlay + sdkBinding: + sdk: lightning-base-components + export: lightning-modal + webStandardMapping: + htmlElement: dialog + ariaRole: dialog + semanticType: overlay + props: + size: + type: string + enum: [small, medium, large] + default: medium + label: + type: string + description: Modal header label (aria-label) + slots: + default: + description: Modal body content + required: true + header: + description: Modal header content + required: false + footer: + description: Modal footer content + required: false + accessibility: + keyboardSupport: true + screenReaderSupport: true + focusManagement: "Focus automatically trapped within modal" + ariaSupport: true + +extensionPoints: + - id: record-page + name: Record Page + type: page + extensionType: codedComponents + description: | + Components displayed on Lightning Record Pages. Can access current + record context and be configured in Lightning App Builder. + supportedComponents: + - all + constraints: + responsive: true + sldsRequired: true + context: + provides: + - recordId + - objectApiName + actions: + - navigateToRecord + - refreshView + - fireToast + configuration: + targets: + - lightning__RecordPage + configurable: true + supportsDesignAttributes: true + + - id: app-page + name: App Page + type: page + extensionType: codedComponents + description: | + Components for custom Lightning App Pages. Can be configured + in Lightning App Builder and accept design attributes. + supportedComponents: + - all + constraints: + responsive: true + sldsRequired: true + context: + provides: + - pageReference + - user + actions: + - navigate + - fireToast + configuration: + targets: + - lightning__AppPage + configurable: true + supportsDesignAttributes: true + + - id: home-page + name: Home Page + type: page + extensionType: codedComponents + description: Components displayed on Lightning Home Pages + supportedComponents: + - all + constraints: + responsive: true + sldsRequired: true + configuration: + targets: + - lightning__HomePage + configurable: true + + - id: utility-bar + name: Utility Bar + type: utility + extensionType: codedComponents + description: | + Dockable utility items in the footer of Lightning Experience. + Useful for tools that users need constant access to. + supportedComponents: + - all + constraints: + responsive: true + sldsRequired: true + maxHeight: 480px + context: + provides: + - utilityAPI + actions: + - minimizeUtility + - maximizeUtility + - closeUtility + configuration: + targets: + - lightning__UtilityBar + configurable: true + + - id: quick-action + name: Quick Action + type: action + extensionType: codedComponents + description: | + Component launched as a quick action from records or global header. + Typically used for creating records or performing quick tasks. + supportedComponents: + - all + constraints: + responsive: true + sldsRequired: true + context: + provides: + - recordId + - objectApiName + actions: + - closeAction + - setActionResult + configuration: + targets: + - lightning__QuickAction + configurable: false + + - id: flow-screen + name: Flow Screen + type: screen + extensionType: codedComponents + description: | + Components usable within Flow screens. Can define input/output + properties for Flow variable integration. + supportedComponents: + - all + constraints: + sldsRequired: true + context: + provides: + - flowAPI + actions: + - validate + - navigateNext + - navigatePrevious + configuration: + targets: + - lightning__FlowScreen + configurable: true + supportsFlowVariables: true + + - id: tab + name: Lightning Tab + type: tab + extensionType: codedComponents + description: Components that can be opened as tabs in Lightning Experience + supportedComponents: + - all + constraints: + responsive: true + sldsRequired: true + configuration: + targets: + - lightning__Tab + configurable: true + +policies: + componentRequirement: + level: recommended + scope: public-apps + rationale: | + Salesforce recommends using Lightning Base Components for consistency, + accessibility, and automatic SLDS styling. However, custom components + are allowed if they follow SLDS guidelines and security requirements. + + For AppExchange apps, use of base components is strongly recommended + to pass security review and design review. + + customComponents: + allowed: true + documentation: https://developer.salesforce.com/docs/platform/lwc/guide/create-components.html + constraints: + - Must follow SLDS design guidelines + - Must implement proper accessibility (WCAG 2.1 AA) + - Must use LockerService-compatible JavaScript + - Must respect Salesforce governor limits + - Cannot include security vulnerabilities (XSS, CSRF, etc.) + - Must handle errors gracefully + - Custom styling must align with SLDS tokens + + publishing: + privateDeployment: + componentRequirement: recommended + customComponentsAllowed: true + reviewRequired: false + notes: | + Private deployments have full flexibility but should follow best + practices for maintainability and user experience. + + managedPackage: + componentRequirement: required + customComponentsAllowed: true + reviewRequired: true + securityReviewRequired: true + notes: | + Managed packages require adherence to packaging best practices + and may undergo review depending on distribution. + + appExchange: + componentRequirement: required + customComponentsAllowed: true + certificationRequired: true + securityReviewRequired: true + designReviewRequired: true + notes: | + AppExchange apps must pass comprehensive security review including + manual code review, automated scans, and penetration testing. + Design review ensures SLDS compliance and UX quality. + + designGuidelines: + required: true + designSystem: Salesforce Lightning Design System (SLDS) + designSystemUrl: https://www.lightningdesignsystem.com/ + designTokensProvided: true + accessibility: + standard: WCAG 2.1 AA + required: true + documentation: https://www.lightningdesignsystem.com/accessibility/overview/ + + security: + lockerService: + enabled: true + description: | + LockerService enforces security by isolating components in separate + namespaces, providing secure wrappers for DOM APIs, and preventing + access to non-published component properties. + documentation: https://developer.salesforce.com/docs/platform/lwc/guide/security-locker-service.html + + governorLimits: + enforced: true + description: | + Salesforce enforces governor limits on API calls, DML operations, + SOQL queries, heap size, and CPU time to ensure multi-tenant performance. + documentation: https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/ + + contentSecurityPolicy: + enforced: true + description: | + Strict CSP prevents inline scripts and unsafe-eval. All JavaScript + must be in component bundles or secure static resources. + +renderingEngines: + lwc: + type: webComponents + name: Lightning Web Components + description: | + LWC uses native Web Components standards (Custom Elements, Shadow DOM, + ES Modules) with a thin performance-optimized framework layer. + sandboxing: + shadowDOM: true + lockerService: true + restrictedGlobals: true + secureWrappers: true + + aura: + type: legacy + name: Aura Components (Legacy) + description: | + Legacy Aura framework. Can interoperate with LWC but new development + should use LWC. Aura components can contain LWC components. + deprecated: false + interoperability: + canContainLWC: true + canBeContainedByLWC: false + +extensionType: codedComponents + +compliance: + appExchangeSecurity: + required: true + level: mandatory + description: | + AppExchange Security Review is mandatory for all listings. Includes: + - Automated security scans (Checkmarx) + - Manual code review + - Penetration testing + - Privacy and data handling review + - Third-party library assessment + documentation: https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/security_review.htm + requirements: + - No critical or high severity vulnerabilities + - Proper input validation and output encoding + - Secure authentication and authorization + - Encrypted data transmission + - Compliance with Salesforce security best practices + - OWASP Top 10 mitigation + + accessibility: + required: true + standard: WCAG 2.1 AA + description: | + Accessibility is required for AppExchange and strongly recommended + for all Salesforce applications. SLDS components include built-in + accessibility features. + documentation: https://www.lightningdesignsystem.com/accessibility/overview/ + requirements: + - Keyboard navigation support + - Screen reader compatibility + - Proper ARIA labels and roles + - Sufficient color contrast + - Focus management + - Semantic HTML structure + + soc2: + applicable: true + description: | + Salesforce Platform maintains SOC 2 Type II certification. + Apps on the platform benefit from this certified infrastructure. + documentation: https://compliance.salesforce.com/ + + gdpr: + applicable: true + description: | + Apps must comply with GDPR when handling EU personal data. + Salesforce provides tools for data privacy compliance. + documentation: https://www.salesforce.com/gdpr/ + + hipaa: + applicable: true + notes: | + HIPAA compliance available for Salesforce orgs with signed BAA. + Apps handling PHI must follow additional security requirements. + documentation: https://www.salesforce.com/solutions/industries/healthcare/hipaa-compliance/ + +i18n: + supported: true + framework: Translation Workbench + description: | + Salesforce provides comprehensive internationalization support through + Translation Workbench, Custom Labels, and automatic locale detection. + features: + customLabels: + supported: true + description: | + Custom Labels are text values stored centrally and translated + into multiple languages. Accessible in LWC via @salesforce/label. + documentation: https://developer.salesforce.com/docs/platform/lwc/guide/create-labels.html + + translationWorkbench: + supported: true + description: | + Translation Workbench manages translations for custom labels, + field labels, picklist values, and more. + documentation: https://help.salesforce.com/s/articleView?id=sf.workbench_overview.htm + + localeDetection: + automatic: true + description: | + User locale automatically detected from user preferences. + Components can access via $i18n wire adapter. + + supportedLocales: + - en_US + - de + - es + - fr + - it + - ja + - ko + - pt_BR + - zh_CN + - zh_TW + - many more... + + dateTimeFormatting: + automatic: true + description: | + lightning-formatted-date-time automatically formats dates + according to user locale. + + numberFormatting: + automatic: true + description: | + lightning-formatted-number automatically formats numbers + and currency according to user locale. + + rightToLeft: + supported: true + description: SLDS includes RTL support for Arabic, Hebrew, etc. + +jsonFormsIntegration: + supported: false + notes: | + Salesforce uses lightning-record-form and lightning-*-input components + rather than JSON Forms. Dynamic forms can be built with dynamic field + rendering. + +mcpAppsIntegration: + supported: false + notes: Not yet integrated with MCP Apps specification + +notes: | + Additional Salesforce LWC Considerations: + + 1. Development Environment: + - Salesforce CLI (sf) for project creation and deployment + - VS Code with Salesforce Extensions recommended + - Local Development Server available (API 58.0+) + + 2. Testing: + - Jest for unit testing + - Lightning Testing Service (LTS) for integration tests + - Salesforce DX scratch orgs for testing + + 3. Deployment: + - Metadata API + - Change Sets + - Salesforce DX / Source-Driven Development + - CI/CD pipelines with Salesforce CLI + + 4. Performance: + - Components lazy-loaded by default + - Wire service provides automatic caching + - Governor limits enforce efficient code + + 5. Versioning: + - Components versioned by Salesforce API version + - Backward compatibility maintained + - API versions updated three times per year diff --git a/specs/fenestra/examples/0.1.0/shopify.fenestra.yaml b/specs/fenestra/examples/0.1.0/shopify.fenestra.yaml new file mode 100644 index 0000000..845fabe --- /dev/null +++ b/specs/fenestra/examples/0.1.0/shopify.fenestra.yaml @@ -0,0 +1,1400 @@ +# Fenestra Document: Shopify Extensions Ecosystem +# +# Shopify represents a HYBRID extension ecosystem with multiple surfaces requiring +# different integration approaches: +# +# 1. Admin Embedded Apps: iframe + App Bridge SDK for communication +# 2. Checkout UI Extensions: React components with limited Checkout UI component set +# 3. Post-purchase Extensions: React components with Checkout UI components +# 4. POS UI Extensions: Native mobile components +# 5. Theme App Extensions: Liquid templates + custom sections +# +# Key Characteristics: +# - Multiple component catalogs for different surfaces (Polaris vs Checkout UI) +# - Hybrid extensionType (iframe for admin, codedComponents for checkout) +# - App Bridge for iframe-admin communication +# - Strict App Store review for public apps +# - Multi-language support via Shopify Markets +# - Different security models per surface + +fenestra: "0.1.0" + +info: + title: Shopify Extensions Ecosystem + version: "1.0.0" + summary: Multi-surface extension platform for commerce applications + description: | + Shopify provides multiple extension surfaces for building commerce applications, + each with different technical approaches and component requirements: + + **Admin Extensions (Embedded Apps):** + - Embedded in iframe within Shopify Admin + - Use App Bridge SDK for communication with host + - Polaris design system for UI consistency + - Full React/custom component flexibility + + **Checkout UI Extensions:** + - React components running in sandboxed runtime + - Limited to Checkout UI component set (NOT Polaris) + - Strict performance and security requirements + - No iframe - direct component rendering + + **Post-purchase Extensions:** + - React components with Checkout UI components + - Displayed after payment confirmation + - Limited time window for customer interaction + + **POS UI Extensions:** + - Native iOS/Android components + - Used in Shopify POS app + - Touch-optimized for retail environments + + **Theme App Extensions:** + - Liquid templates and custom sections + - Integrated into merchant themes + - No React - uses Shopify's templating language + + This hybrid approach allows Shopify to balance flexibility (admin apps), + performance (checkout extensions), and security (sandboxed runtimes). + + contact: + name: Shopify Developer Support + url: https://shopify.dev/support + email: developers@shopify.com + +platform: + name: Shopify + vendor: Shopify Inc. + documentation: https://shopify.dev/docs/apps + appMarketplace: https://apps.shopify.com/ + +# ============================================================================= +# SDK DEFINITIONS +# ============================================================================= + +sdks: + shopify-app-bridge: + name: Shopify App Bridge + packageManager: npm + package: "@shopify/app-bridge" + version: "^3.7.0" + platform: web + documentation: https://shopify.dev/docs/api/app-bridge + repository: https://github.com/Shopify/app-bridge + installCommand: npm install @shopify/app-bridge + description: | + App Bridge enables communication between embedded admin apps (running in + iframes) and the Shopify Admin host. It provides a JavaScript API for: + - Navigation within Shopify Admin + - Opening modals and toasts + - Triggering actions (ResourcePicker, etc.) + - Context awareness (shop, user, etc.) + - TitleBar and navigation customization + + App Bridge uses postMessage for secure cross-origin communication. + + exports: + createApp: + type: utility + description: Initialize App Bridge connection + actions: + type: utility + description: Namespace for all App Bridge actions + + subpackages: + actions: + package: "@shopify/app-bridge/actions" + description: App Bridge action modules + exports: + TitleBar: + type: utility + description: Customize app title bar in admin + Toast: + type: utility + description: Show toast notifications + Modal: + type: utility + description: Open modals + ResourcePicker: + type: utility + description: Pick products, collections, variants + Navigation: + type: utility + description: Navigate within Shopify Admin + Redirect: + type: utility + description: Redirect to URLs + Loading: + type: utility + description: Show/hide loading indicator + ContextualSaveBar: + type: utility + description: Show save/discard bar + Features: + type: utility + description: Check feature availability + + shopify-app-bridge-react: + name: Shopify App Bridge React + packageManager: npm + package: "@shopify/app-bridge-react" + version: "^3.7.0" + platform: web + documentation: https://shopify.dev/docs/api/app-bridge/previous-versions/react-components + repository: https://github.com/Shopify/app-bridge + installCommand: npm install @shopify/app-bridge-react + description: | + React bindings for App Bridge, providing hooks and components for + seamless integration in React apps. + + exports: + Provider: + type: component + description: App Bridge provider for React apps + useAppBridge: + type: hook + description: Access App Bridge instance + useNavigate: + type: hook + description: Navigate within Shopify Admin + TitleBar: + type: component + description: Configure title bar + ResourcePicker: + type: component + description: Product/collection picker + Modal: + type: component + description: Modal dialogs + Toast: + type: component + description: Toast notifications + + shopify-polaris: + name: Shopify Polaris + packageManager: npm + package: "@shopify/polaris" + version: "^12.0.0" + platform: web + documentation: https://polaris.shopify.com/ + repository: https://github.com/Shopify/polaris + installCommand: npm install @shopify/polaris + description: | + Polaris is Shopify's design system for building admin apps. It provides + React components, design tokens, and guidelines for creating consistent, + accessible experiences in Shopify Admin. + + **IMPORTANT:** Polaris is ONLY for admin apps. Checkout extensions use + the separate Checkout UI component set. + + exports: + # Layout Components + Page: + type: component + description: Top-level page container with header + Layout: + type: component + description: Page layout with sections + Card: + type: component + description: Content container + Stack: + type: component + description: Flex layout for spacing items + + # Action Components + Button: + type: component + description: Standard button + ButtonGroup: + type: component + description: Group related buttons + + # Form Components + TextField: + type: component + description: Text input field + Select: + type: component + description: Dropdown select + Checkbox: + type: component + description: Checkbox input + RadioButton: + type: component + description: Radio button + ChoiceList: + type: component + description: List of checkboxes or radios + + # Data Display + DataTable: + type: component + description: Table for tabular data + ResourceList: + type: component + description: List of resources with bulk actions + ResourceItem: + type: component + description: Item within ResourceList + + # Feedback + Banner: + type: component + description: Contextual messages and alerts + Toast: + type: component + description: Brief messages (deprecated - use App Bridge) + Spinner: + type: component + description: Loading indicator + + # Navigation + Tabs: + type: component + description: Tab navigation + + # Overlays + Modal: + type: component + description: Modal dialogs (deprecated - use App Bridge) + Popover: + type: component + description: Floating content + + # Icons + Icon: + type: component + description: Icon component + + checkout-ui-extensions: + name: Checkout UI Extensions + packageManager: npm + package: "@shopify/ui-extensions/checkout" + version: "^2024.10.0" + platform: web + documentation: https://shopify.dev/docs/api/checkout-ui-extensions + repository: https://github.com/Shopify/ui-extensions + installCommand: npm install @shopify/ui-extensions + description: | + Checkout UI Extensions provide a LIMITED set of React components for + building extensions in Shopify checkout. These components are DIFFERENT + from Polaris and are optimized for the checkout experience. + + Key differences from Polaris: + - Smaller component set (performance-critical) + - Checkout-specific components (e.g., DeliveryOptions) + - No direct DOM access (sandboxed runtime) + - Automatic accessibility and responsive design + - Localization handled by Shopify + + exports: + # Layout + BlockStack: + type: component + description: Vertical stack layout + InlineStack: + type: component + description: Horizontal inline layout + Grid: + type: component + description: Grid layout + View: + type: component + description: Generic container + + # Typography + Text: + type: component + description: Text with semantic styles + Heading: + type: component + description: Heading text + + # Forms + TextField: + type: component + description: Text input + Checkbox: + type: component + description: Checkbox input + Select: + type: component + description: Select dropdown + + # Actions + Button: + type: component + description: Action button + Link: + type: component + description: Hyperlink + + # Display + Image: + type: component + description: Image display + Icon: + type: component + description: Icon display + Badge: + type: component + description: Status badge + + # Checkout-specific + Choice: + type: component + description: Radio or checkbox choice + Divider: + type: component + description: Visual separator + + # Hooks + useExtensionApi: + type: hook + description: Access extension runtime API + useCartLines: + type: hook + description: Access cart line items + useShop: + type: hook + description: Access shop information + useBuyerIdentity: + type: hook + description: Access customer information + + shopify-cli: + name: Shopify CLI + packageManager: npm + package: "@shopify/cli" + version: "^3.51.0" + documentation: https://shopify.dev/docs/api/shopify-cli + installCommand: npm install -g @shopify/cli + description: | + Command-line interface for building Shopify apps and extensions. + + cliTool: + package: "@shopify/cli" + installCommand: npm install -g @shopify/cli + commands: + init: "shopify app init" + dev: "shopify app dev" + deploy: "shopify app deploy" + generate: "shopify app generate extension" + +# ============================================================================= +# COMPONENT CATALOG - POLARIS (Admin Apps) +# ============================================================================= + +componentCatalog: + categories: + admin-layout: + name: Admin Layout + description: Polaris layout components for admin apps + components: + - Page + - Layout + - Card + - Stack + + admin-actions: + name: Admin Actions + description: Polaris action components for admin apps + components: + - Button + - ButtonGroup + + admin-forms: + name: Admin Forms + description: Polaris form components for admin apps + components: + - TextField + - Select + - Checkbox + - RadioButton + + admin-data: + name: Admin Data Display + description: Polaris data components for admin apps + components: + - DataTable + - ResourceList + + checkout-layout: + name: Checkout Layout + description: Checkout UI layout components + components: + - BlockStack + - InlineStack + - Grid + - View + + checkout-forms: + name: Checkout Forms + description: Checkout UI form components + components: + - CheckoutTextField + - CheckoutCheckbox + - CheckoutSelect + + components: + # ========================================================================== + # POLARIS COMPONENTS (Admin Apps) + # ========================================================================== + + Page: + name: Page + description: | + Top-level container for admin pages. Provides consistent header, + breadcrumbs, and action areas. Used in embedded admin apps. + category: admin-layout + sdkBinding: + sdk: shopify-polaris + export: Page + importPath: "@shopify/polaris" + webStandardMapping: + htmlElement: div + ariaRole: main + semanticType: container + props: + type: object + properties: + title: + type: string + description: Page title + required: true + primaryAction: + type: object + description: Primary action button config + secondaryActions: + type: array + description: Secondary action buttons + breadcrumbs: + type: array + description: Breadcrumb navigation + slots: + default: + description: Page content + required: true + accessibility: + keyboardSupport: true + screenReaderSupport: true + focusManagement: Automatic heading hierarchy + examples: + - title: Basic Page + code: | + import { Page, Card } from '@shopify/polaris'; + + function MyPage() { + return ( + + +

Page content goes here

+
+
+ ); + } + language: jsx + + Card: + name: Card + description: | + Container for grouping related content. Polaris Card provides + sections, headers, and actions. + category: admin-layout + sdkBinding: + sdk: shopify-polaris + export: Card + importPath: "@shopify/polaris" + webStandardMapping: + htmlElement: div + semanticType: container + props: + type: object + properties: + title: + type: string + description: Card title + sectioned: + type: boolean + description: Automatically wrap content in section + actions: + type: array + description: Card header actions + examples: + - title: Card with Sections + code: | + import { Card } from '@shopify/polaris'; + + +

Order information

+
+ language: jsx + + Button: + name: Button + description: Standard action button with Polaris styling + category: admin-actions + sdkBinding: + sdk: shopify-polaris + export: Button + importPath: "@shopify/polaris" + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + type: object + properties: + children: + type: string + description: Button text + primary: + type: boolean + description: Primary button style + destructive: + type: boolean + description: Destructive action style + disabled: + type: boolean + loading: + type: boolean + description: Show loading state + onClick: + type: function + variants: + - primary + - plain + - destructive + accessibility: + keyboardSupport: true + screenReaderSupport: true + + TextField: + name: TextField + description: Text input field with label and validation + category: admin-forms + sdkBinding: + sdk: shopify-polaris + export: TextField + importPath: "@shopify/polaris" + webStandardMapping: + htmlElement: input + ariaRole: textbox + semanticType: input + props: + type: object + properties: + label: + type: string + description: Input label + value: + type: string + description: Input value + onChange: + type: function + description: Change handler + type: + type: string + enum: [text, email, number, password, search, tel, url, date, datetime-local, month, time, week] + error: + type: string + description: Error message + helpText: + type: string + description: Help text below input + accessibility: + keyboardSupport: true + screenReaderSupport: true + ariaSupport: true + + DataTable: + name: DataTable + description: Table for displaying tabular data + category: admin-data + sdkBinding: + sdk: shopify-polaris + export: DataTable + importPath: "@shopify/polaris" + webStandardMapping: + htmlElement: table + ariaRole: table + semanticType: display + props: + type: object + properties: + columnContentTypes: + type: array + description: Content types for each column + headings: + type: array + description: Column headings + rows: + type: array + description: Table data rows + sortable: + type: array + description: Sortable columns + accessibility: + keyboardSupport: true + screenReaderSupport: true + + # ========================================================================== + # CHECKOUT UI COMPONENTS (Different from Polaris!) + # ========================================================================== + + BlockStack: + name: BlockStack + description: | + Vertical stack layout for Checkout UI extensions. + This is part of Checkout UI components, NOT Polaris. + category: checkout-layout + sdkBinding: + sdk: checkout-ui-extensions + export: BlockStack + importPath: "@shopify/ui-extensions/checkout" + webStandardMapping: + htmlElement: div + semanticType: layout + props: + type: object + properties: + spacing: + type: string + enum: [none, extraTight, tight, base, loose, extraLoose] + inlineAlignment: + type: string + enum: [start, center, end] + examples: + - title: Vertical Stack in Checkout + code: | + import { BlockStack, Text } from '@shopify/ui-extensions/checkout'; + + + First item + Second item + + language: jsx + + CheckoutTextField: + name: TextField + description: | + Text input for Checkout UI extensions. Different implementation + than Polaris TextField - optimized for checkout performance. + category: checkout-forms + sdkBinding: + sdk: checkout-ui-extensions + export: TextField + importPath: "@shopify/ui-extensions/checkout" + webStandardMapping: + htmlElement: input + ariaRole: textbox + semanticType: input + props: + type: object + properties: + label: + type: string + value: + type: string + onChange: + type: function + error: + type: string + accessibility: + keyboardSupport: true + screenReaderSupport: true + notes: | + Checkout UI components handle accessibility automatically. + Developers cannot modify ARIA attributes directly. + + CheckoutButton: + name: Button + description: | + Action button for Checkout UI extensions. Limited variants compared + to Polaris Button to maintain checkout consistency. + category: checkout-actions + sdkBinding: + sdk: checkout-ui-extensions + export: Button + importPath: "@shopify/ui-extensions/checkout" + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + type: object + properties: + onPress: + type: function + description: Press handler + disabled: + type: boolean + loading: + type: boolean + variants: + - primary + - secondary + accessibility: + keyboardSupport: true + screenReaderSupport: true + +# ============================================================================= +# EXTENSION POINTS +# ============================================================================= + +extensionPoints: + # =========================================================================== + # ADMIN EMBEDDED APP (iframe + App Bridge) + # =========================================================================== + + - id: admin-embedded-app + name: Admin Embedded App + type: fullPage + extensionType: iframe + description: | + Apps embedded in Shopify Admin via iframe. Use App Bridge for + communication with the Shopify Admin host. Can use Polaris components + for consistent UI, but custom React components are also allowed. + + **Key Characteristics:** + - Runs in iframe within Shopify Admin + - Uses postMessage via App Bridge for host communication + - Full flexibility - any React framework, custom components + - Polaris RECOMMENDED but not required + - Access to Shopify APIs via session tokens + + **Different from checkout extensions:** Admin apps have more freedom + but less integration. Checkout extensions are rendered directly by + Shopify with strict component limitations. + + extensionTypeConfig: + sandboxAttributes: + - allow-same-origin + - allow-scripts + - allow-forms + + cspRequirements: | + Apps must be served over HTTPS with appropriate CSP headers. + Frame-ancestors must allow Shopify domains. + + sizeConstraints: + resizable: true + minWidth: 320 + minHeight: 400 + + communication: + globalObject: window.shopify + package: "@shopify/app-bridge" + cdn: https://cdn.shopify.com/shopifycloud/app-bridge.js + + initialization: + method: createApp + async: true + + namespaces: + TitleBar: + description: Configure app title bar + methods: [create, set, update] + Toast: + description: Show toast notifications + methods: [create, show] + Modal: + description: Open modals + methods: [create, open, close] + ResourcePicker: + description: Pick products/collections + methods: [create, subscribe] + Navigation: + description: Navigate in admin + methods: [navigate] + + capabilities: + context: true + uiActions: true + dataActions: true + events: true + + asyncPattern: promises + + supportedComponents: + - All Polaris components + - Custom React components + - Standard HTML elements + + constraints: + responsive: true + httpsRequired: true + + context: + provides: + - shop + - apiKey + - host + - sessionToken + actions: + - navigate + - openModal + - showToast + - pickResource + - redirect + + # =========================================================================== + # CHECKOUT UI EXTENSIONS (codedComponents - NOT iframe!) + # =========================================================================== + + - id: checkout-ui-extension + name: Checkout UI Extension + type: embedded + extensionType: codedComponents + description: | + React components that run in Shopify's checkout. These are NOT iframes - + they're rendered directly by Shopify's checkout runtime. + + **CRITICAL DIFFERENCES from Admin Apps:** + - NOT in iframe - runs in sandboxed JavaScript runtime + - MUST use Checkout UI components (NOT Polaris) + - Limited component set for performance + - No direct DOM access + - No external network requests from component code + - Automatic accessibility and localization + - Strict performance budgets + + **Extension targets:** + - purchase.checkout.block.render (main checkout) + - purchase.checkout.shipping-option-item.render-after + - purchase.checkout.payment-method-list.render-after + - purchase.checkout.delivery-address.render-after + + extensionTypeConfig: + sdk: checkout-ui-extensions + framework: react + + runtime: + type: sandboxedIframe + bundling: platformBuild + description: | + Checkout extensions run in a sandboxed JavaScript runtime. + Shopify builds and bundles your extension code. You cannot + bundle third-party libraries arbitrarily. + + hostInteraction: + package: "@shopify/ui-extensions/checkout" + + initialization: + method: extend + async: false + + capabilities: + context: true + uiActions: false + dataActions: true + events: true + + asyncPattern: promises + + supportedComponents: + - BlockStack + - InlineStack + - Grid + - View + - Text + - Heading + - CheckoutTextField + - CheckoutCheckbox + - CheckoutSelect + - CheckoutButton + - Link + - Image + - Icon + - Badge + - Choice + - Divider + + constraints: + responsive: true + performanceBudget: + maxBundleSize: 50kb + maxRenderTime: 100ms + + context: + provides: + - cart + - shop + - buyerIdentity + - settings + actions: + - applyCartLinesChange + - applyDiscountCodeChange + - applyAttributeChange + + # =========================================================================== + # POST-PURCHASE EXTENSIONS + # =========================================================================== + + - id: post-purchase-extension + name: Post-purchase Extension + type: fullPage + extensionType: codedComponents + description: | + Full-page extension shown after checkout completion. Allows merchants + to offer post-purchase upsells with one-click purchasing (no re-entering + payment info). Uses Checkout UI components. + + **Constraints:** + - Time-limited (customer can skip after countdown) + - Must use Checkout UI components + - Can modify order with customer consent + - Automatic payment processing (no re-auth needed) + + extensionTypeConfig: + sdk: checkout-ui-extensions + framework: react + runtime: + type: sandboxedIframe + bundling: platformBuild + + supportedComponents: + - BlockStack + - InlineStack + - Text + - Heading + - CheckoutButton + - Image + + constraints: + maxDuration: 60s + responsive: true + + context: + provides: + - initialPurchase + - shop + - buyerIdentity + actions: + - updateOrder + - completeOrder + + # =========================================================================== + # POS UI EXTENSIONS (Native Mobile) + # =========================================================================== + + - id: pos-ui-extension + name: POS UI Extension + type: modal + extensionType: codedComponents + description: | + Native mobile components for Shopify POS (Point of Sale) app. + Available on iOS and Android. Used for custom workflows in retail + environments. + + **Platform-specific:** + - iOS: Swift UI components + - Android: Jetpack Compose components + - NOT web-based - fully native + + extensionTypeConfig: + framework: agnostic + runtime: + type: directExecution + bundling: platformBuild + + supportedComponents: + - Native mobile components (platform-specific) + + constraints: + responsive: false + touchOptimized: true + + context: + provides: + - cart + - location + - staff + actions: + - addCartLine + - completeCheckout + +# ============================================================================= +# POLICIES +# ============================================================================= + +policies: + componentRequirement: + level: required + scope: checkout + rationale: | + Checkout UI extensions MUST use the provided Checkout UI component set. + This is non-negotiable for performance, security, and accessibility. + + Admin apps SHOULD use Polaris but can use custom components with proper + accessibility and design considerations. + + customComponents: + allowed: true + constraints: + - Admin apps can use custom components + - Checkout extensions CANNOT use custom components + - All custom components must be accessible (WCAG 2.1 AA) + - Custom components should align with Polaris design principles + documentation: https://shopify.dev/docs/apps/design-guidelines + + publishing: + customApps: + componentRequirement: recommended + customComponentsAllowed: true + reviewRequired: false + notes: | + Custom apps (private to single merchant) have full flexibility. + + publicApps: + componentRequirement: required + customComponentsAllowed: true + reviewRequired: true + designReviewRequired: false + accessibilityAuditRequired: true + notes: | + Public apps (installable from App Store) must pass security and + functionality review. Polaris usage strongly recommended. + + appStoreListings: + componentRequirement: required + customComponentsAllowed: true + certificationRequired: false + securityReviewRequired: true + designReviewRequired: true + accessibilityAuditRequired: true + notes: | + Apps listed in Shopify App Store undergo comprehensive review including + security testing, design review, and functionality testing. + + designGuidelines: + required: true + designSystem: Shopify Polaris + designSystemUrl: https://polaris.shopify.com/ + designTokensProvided: true + scope: admin-apps + notes: | + Polaris design system is for admin apps only. Checkout extensions + use Checkout UI components with automatic styling. + + security: + appBridge: + required: true + scope: admin-embedded-apps + description: | + Admin embedded apps must use App Bridge for secure communication. + Direct iframe manipulation or insecure postMessage patterns are + prohibited. + documentation: https://shopify.dev/docs/api/app-bridge + + sessionTokens: + required: true + description: | + Apps must use session tokens (JWT) for authenticating API requests. + Session tokens are short-lived and scoped to the current shop. + documentation: https://shopify.dev/docs/apps/auth/oauth/session-tokens + + webhooks: + signatureVerification: required + description: | + Apps must verify HMAC signatures on all webhook requests to ensure + they originated from Shopify. + documentation: https://shopify.dev/docs/apps/webhooks/configuration/https + +# ============================================================================= +# RENDERING ENGINES +# ============================================================================= + +renderingEngines: + admin-app-iframe: + type: custom + name: Admin App iframe Renderer + description: | + Admin apps run in iframes with App Bridge providing the communication + layer. Apps can use any web framework (React, Vue, vanilla JS, etc.) + as long as they integrate App Bridge. + + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-same-origin + - allow-scripts + - allow-forms + cspPolicy: | + Apps must be served over HTTPS and set appropriate CSP headers. + + checkout-runtime: + type: react + name: Checkout Extension Runtime + description: | + Checkout extensions run in Shopify's custom React runtime. This is + NOT a standard iframe - it's a sandboxed JavaScript execution environment + with limited APIs. + + **Key restrictions:** + - No direct DOM access + - No window or document globals + - No external network requests + - Limited to provided Checkout UI components + - Automatic tree-shaking and code splitting + + sandboxing: + iframeSandbox: true + customRuntime: true + restrictedAPIs: true + +# ============================================================================= +# EXTENSIONS +# ============================================================================= + +x-compliance: + security: + platformCertifications: + - PCI DSS Level 1 + - SOC 2 Type II + - ISO 27001 + + extensionRequirements: + httpsOnly: true + cspCompliance: true + noInlineScripts: false + noExternalScripts: false + + securityReview: + required: true + scope: marketplace + description: | + Apps submitted to Shopify App Store undergo security review including: + - Automated vulnerability scanning + - Manual code review for critical apps + - API usage verification + - Webhook signature verification + - OAuth flow validation + + dataHandling: + piiAllowed: true + piiMustEncrypt: true + dataRetentionPolicy: required + + documentation: https://shopify.dev/docs/apps/store/security + + privacy: + platformCompliance: + gdpr: true + ccpa: true + + dataResidency: + available: false + notes: Shopify stores data in centralized regions + + extensionRequirements: + privacyPolicyRequired: true + consentManagement: both + dataProcessingAgreement: required + notes: | + Apps must provide a privacy policy and comply with merchant's + customer consent settings. Apps that access customer data must + sign a Data Processing Agreement. + + userRights: + dataExportSupported: true + dataDeletionSupported: true + notes: | + Apps must support data export and deletion requests via + GDPR webhooks (customers/data_request, customers/redact). + + documentation: https://shopify.dev/docs/apps/store/data-protection + + sharedResponsibility: + platformHandles: + - Payment processing (PCI compliance) + - Customer data encryption at rest + - Infrastructure security + - DDoS protection + - SSL/TLS certificates + - Checkout security and fraud prevention + - App Bridge security (postMessage validation) + - Checkout extension sandboxing + - Customer consent management (via Customer Privacy API) + + developerHandles: + - App server security (HTTPS, firewalls) + - API credential security + - Webhook signature verification + - Session token validation + - Data encryption in transit (to external services) + - Third-party service security + - Privacy policy and terms of service + - GDPR webhook implementation (data export/deletion) + - Secure storage of merchant/customer data + + documentation: https://shopify.dev/docs/apps/store/security/shared-responsibility + +x-i18n: + platformSupport: + enabled: true + + availableLocales: + # Shopify supports 20+ languages for merchants and customers + - ar # Arabic + - cs # Czech + - da # Danish + - de # German + - en # English + - es # Spanish + - fi # Finnish + - fr # French + - hi # Hindi + - id # Indonesian + - it # Italian + - ja # Japanese + - ko # Korean + - ms # Malay + - nb # Norwegian + - nl # Dutch + - pl # Polish + - pt-BR # Portuguese (Brazil) + - pt-PT # Portuguese (Portugal) + - sv # Swedish + - th # Thai + - tr # Turkish + - vi # Vietnamese + - zh-CN # Chinese (Simplified) + - zh-TW # Chinese (Traditional) + + localeDetection: + method: automatic + sources: + - Shop's primary language + - Customer's browser language (checkout) + - Admin user's language preference + - Shopify Markets (country-specific stores) + + rtlSupport: + enabled: true + languages: + - ar # Arabic + notes: | + Polaris components support RTL automatically. Checkout UI components + handle RTL based on shop locale. + + componentTranslations: + provided: true + scope: all + notes: | + Polaris and Checkout UI components include built-in translations for + all supported languages. Developers don't need to translate component + strings. + + developerRequirements: + translationMechanism: + format: json + bundleLocation: embedded + notes: | + Apps provide translations via locale files. For admin apps, + use i18next or similar. For checkout extensions, use Shopify's + i18n API provided by the runtime. + + marketplaceRequirement: + required: false + minimumLocales: [] + notes: | + Multi-language support not required but recommended for global reach. + Apps should respect shop's primary language. + + formatting: + dates: platform + numbers: platform + currencies: platform + notes: | + Shopify provides formatted dates, numbers, and currencies based on + shop locale and regional settings. Apps should use Shopify's + formatting APIs rather than implementing their own. + + shopifyMarkets: + description: | + Shopify Markets allows merchants to sell globally with country-specific + pricing, languages, and domains. Apps should respect Markets settings + and adapt content accordingly. + documentation: https://shopify.dev/docs/apps/markets + + documentation: https://shopify.dev/docs/apps/best-practices/internationalization + +# ============================================================================= +# NOTES +# ============================================================================= + +x-notes: + hybridArchitecture: | + Shopify's extension ecosystem is HYBRID by design: + + 1. **Admin Apps (iframe + App Bridge):** + - Maximum flexibility for developers + - Polaris for consistent UI but not enforced + - Full web framework freedom (React, Vue, etc.) + - Communication via App Bridge (postMessage) + - Slower integration (iframe overhead) + + 2. **Checkout Extensions (codedComponents):** + - Maximum performance and security + - Strict component limitations (Checkout UI only) + - Sandboxed runtime (no DOM access) + - Direct rendering by Shopify (no iframe) + - Automatic accessibility and localization + + This hybrid approach balances: + - Developer flexibility (admin apps) + - Customer experience (checkout performance) + - Security (checkout sandboxing) + - Consistency (component requirements) + + developmentTools: + cli: | + Shopify CLI (@shopify/cli) is the primary development tool: + - Create apps and extensions + - Local development with hot reload + - Deploy to Shopify partners dashboard + - Generate extension boilerplate + + testing: | + - Admin apps: Standard web testing (Jest, Testing Library) + - Checkout extensions: Limited testing capabilities + - Shopify provides test shops for integration testing + + deployment: | + - Extensions deployed via Shopify CLI + - Apps reviewed via Partners dashboard + - Automatic versioning and rollback support + + performanceConsiderations: + adminApps: | + Admin apps run in iframes with App Bridge overhead. Best practices: + - Minimize postMessage calls + - Optimize bundle size + - Use code splitting + - Lazy load routes + + checkoutExtensions: | + Checkout extensions have strict performance budgets: + - Max 50kb bundle size + - Max 100ms render time + - No blocking network requests + - Automatic performance monitoring + - Extensions that exceed budgets may be disabled + + multiSurfaceSupport: | + Apps can provide multiple extension types: + - Admin embedded app for merchant configuration + - Checkout UI extension for customer-facing features + - Post-purchase extension for upsells + - Theme app extension for storefront integration + - Function extension for backend logic + + Each surface has different technical requirements and component catalogs. diff --git a/specs/fenestra/examples/0.1.0/slack.fenestra.yaml b/specs/fenestra/examples/0.1.0/slack.fenestra.yaml new file mode 100644 index 0000000..0e73f75 --- /dev/null +++ b/specs/fenestra/examples/0.1.0/slack.fenestra.yaml @@ -0,0 +1,1839 @@ +# Fenestra Document: Slack Block Kit +# +# Slack Block Kit represents a declarative, JSON-based UI framework. +# Apps MUST use Block Kit blocks and elements - no custom components allowed. + +fenestra: "0.1.0" + +info: + title: Slack Block Kit UI Framework + version: "2.0.0" + description: | + Block Kit is Slack's UI framework for building rich, interactive app experiences. + It provides a declarative JSON structure for creating messages, modals, and + app home interfaces. + + Key characteristic: Block Kit is REQUIRED - apps must use the provided blocks + and interactive elements exclusively. All UI is defined as JSON structures, + not coded components. + + contact: + name: Slack Platform Team + url: https://api.slack.com/support + email: developers@slack.com + +platform: + name: Slack + vendor: Slack Technologies, LLC (Salesforce) + documentation: https://api.slack.com/block-kit + builderTool: https://app.slack.com/block-kit-builder + appMarketplace: https://slack.com/apps + changelog: https://api.slack.com/changelog + +sdks: + slack-bolt: + name: Slack Bolt Framework + packageManager: npm + package: "@slack/bolt" + version: "^3.17.0" + repository: https://github.com/slackapi/bolt-js + documentation: https://slack.dev/bolt-js/ + description: | + The Bolt framework for JavaScript provides a simple, modern interface + for building Slack apps with Block Kit UI. + exports: + App: + type: class + description: Main application class for Slack apps + BlockAction: + type: type + description: Type for block action events + ViewSubmitAction: + type: type + description: Type for modal view submissions + ViewClosedAction: + type: type + description: Type for modal view closures + + slack-web-api: + name: Slack Web API Client + packageManager: npm + package: "@slack/web-api" + version: "^6.11.0" + repository: https://github.com/slackapi/node-slack-sdk + documentation: https://slack.dev/node-slack-sdk/web-api + description: | + Official Web API client for Node.js, used to call Slack APIs + including posting messages and opening modals with Block Kit. + exports: + WebClient: + type: class + description: Client for calling Slack Web API methods + ChatPostMessageArguments: + type: interface + description: Arguments for posting messages with blocks + ViewsOpenArguments: + type: interface + description: Arguments for opening modals with blocks + ViewsUpdateArguments: + type: interface + description: Arguments for updating modal views + ViewsPushArguments: + type: interface + description: Arguments for pushing new modal views + +componentCatalog: + categories: + blocks: + name: Layout Blocks + description: Container blocks that structure your app's layout + components: + - section + - divider + - image + - actions + - context + - input + - header + - video + - file + - rich_text + + elements: + name: Interactive Elements + description: Interactive components for user input and actions + components: + - button + - static_select + - external_select + - users_select + - conversations_select + - channels_select + - multi_static_select + - multi_external_select + - multi_users_select + - multi_conversations_select + - multi_channels_select + - overflow + - datepicker + - timepicker + - datetimepicker + - plain_text_input + - email_text_input + - url_text_input + - number_input + - checkboxes + - radio_buttons + - rich_text_input + - file_input + + composition: + name: Composition Objects + description: Reusable objects used within blocks and elements + components: + - text + - option + - option_group + - confirm + - conversation_filter + - dispatch_action_config + - filter + - trigger + + components: + # LAYOUT BLOCKS + + section: + name: Section Block + description: | + A section block displays text, possibly with an accessory element + like a button or image to the side. + category: blocks + sdkBinding: + type: jsonSchema + blockType: section + webStandardMapping: + htmlElement: section + ariaRole: region + semanticType: container + schema: + type: object + required: [type] + properties: + type: + type: string + const: section + text: + $ref: "#/composition/text" + description: Text content (markdown or plain_text) + block_id: + type: string + description: Unique identifier for the block + maxLength: 255 + fields: + type: array + description: Array of text objects displayed in 2-column layout + maxItems: 10 + items: + $ref: "#/composition/text" + accessory: + description: Interactive element or image shown to the right + oneOf: + - $ref: "#/elements/button" + - $ref: "#/elements/static_select" + - $ref: "#/elements/image" + - $ref: "#/elements/datepicker" + - $ref: "#/elements/overflow" + constraints: + maxTextLength: 3000 + maxFieldsLength: 2000 + accessibility: + screenReaderSupport: true + keyboardSupport: true + + divider: + name: Divider Block + description: Visual separator between blocks + category: blocks + sdkBinding: + type: jsonSchema + blockType: divider + webStandardMapping: + htmlElement: hr + semanticType: separator + schema: + type: object + required: [type] + properties: + type: + type: string + const: divider + block_id: + type: string + maxLength: 255 + + image: + name: Image Block + description: Display an image with optional title + category: blocks + sdkBinding: + type: jsonSchema + blockType: image + webStandardMapping: + htmlElement: img + ariaRole: img + semanticType: media + schema: + type: object + required: [type, image_url, alt_text] + properties: + type: + type: string + const: image + image_url: + type: string + format: uri + description: URL of the image + maxLength: 3000 + alt_text: + type: string + description: Alt text for accessibility + maxLength: 2000 + title: + $ref: "#/composition/text" + description: Optional title (plain_text only) + block_id: + type: string + maxLength: 255 + accessibility: + altTextRequired: true + screenReaderSupport: true + + actions: + name: Actions Block + description: Container for interactive elements (buttons, selects, etc.) + category: blocks + sdkBinding: + type: jsonSchema + blockType: actions + webStandardMapping: + htmlElement: div + ariaRole: group + semanticType: container + schema: + type: object + required: [type, elements] + properties: + type: + type: string + const: actions + elements: + type: array + description: Interactive elements + minItems: 1 + maxItems: 25 + items: + oneOf: + - $ref: "#/elements/button" + - $ref: "#/elements/static_select" + - $ref: "#/elements/datepicker" + - $ref: "#/elements/timepicker" + - $ref: "#/elements/overflow" + - $ref: "#/elements/checkboxes" + - $ref: "#/elements/radio_buttons" + block_id: + type: string + maxLength: 255 + constraints: + maxElements: 25 + accessibility: + keyboardSupport: true + screenReaderSupport: true + + context: + name: Context Block + description: Display contextual info with text and/or images + category: blocks + sdkBinding: + type: jsonSchema + blockType: context + webStandardMapping: + htmlElement: aside + ariaRole: complementary + semanticType: metadata + schema: + type: object + required: [type, elements] + properties: + type: + type: string + const: context + elements: + type: array + description: Text objects or images + minItems: 1 + maxItems: 10 + items: + oneOf: + - $ref: "#/composition/text" + - type: object + properties: + type: + const: image + image_url: + type: string + alt_text: + type: string + block_id: + type: string + maxLength: 255 + + input: + name: Input Block + description: Form input container for modals + category: blocks + sdkBinding: + type: jsonSchema + blockType: input + webStandardMapping: + htmlElement: div + ariaRole: group + semanticType: form_field + schema: + type: object + required: [type, label, element] + properties: + type: + type: string + const: input + label: + $ref: "#/composition/text" + description: Label for the input (plain_text only) + element: + description: Input element + oneOf: + - $ref: "#/elements/plain_text_input" + - $ref: "#/elements/email_text_input" + - $ref: "#/elements/url_text_input" + - $ref: "#/elements/number_input" + - $ref: "#/elements/static_select" + - $ref: "#/elements/datepicker" + - $ref: "#/elements/timepicker" + - $ref: "#/elements/checkboxes" + - $ref: "#/elements/radio_buttons" + - $ref: "#/elements/rich_text_input" + dispatch_action: + type: boolean + description: Dispatch payload on input change + block_id: + type: string + maxLength: 255 + hint: + $ref: "#/composition/text" + description: Helpful text below the input + optional: + type: boolean + description: Whether input is optional + default: false + accessibility: + labelRequired: true + screenReaderSupport: true + + header: + name: Header Block + description: Large header text + category: blocks + sdkBinding: + type: jsonSchema + blockType: header + webStandardMapping: + htmlElement: h1 + ariaRole: heading + semanticType: heading + schema: + type: object + required: [type, text] + properties: + type: + type: string + const: header + text: + $ref: "#/composition/text" + description: Header text (plain_text only, max 150 chars) + block_id: + type: string + maxLength: 255 + constraints: + maxTextLength: 150 + + video: + name: Video Block + description: Embed videos from YouTube, Vimeo, etc. + category: blocks + sdkBinding: + type: jsonSchema + blockType: video + webStandardMapping: + htmlElement: video + ariaRole: region + semanticType: media + schema: + type: object + required: [type, video_url, thumbnail_url, alt_text, title] + properties: + type: + type: string + const: video + video_url: + type: string + format: uri + description: Video URL + thumbnail_url: + type: string + format: uri + description: Thumbnail image URL + alt_text: + type: string + description: Alt text for accessibility + maxLength: 200 + title: + $ref: "#/composition/text" + description: Video title (plain_text only) + title_url: + type: string + format: uri + description: Hyperlinked title URL + author_name: + type: string + description: Author name + provider_name: + type: string + description: Provider name (e.g., YouTube) + provider_icon_url: + type: string + format: uri + description: + $ref: "#/composition/text" + block_id: + type: string + maxLength: 255 + + file: + name: File Block + description: Display a remote file + category: blocks + sdkBinding: + type: jsonSchema + blockType: file + schema: + type: object + required: [type, external_id, source] + properties: + type: + type: string + const: file + external_id: + type: string + description: ID of the file + source: + type: string + description: File source (e.g., "remote") + block_id: + type: string + maxLength: 255 + + rich_text: + name: Rich Text Block + description: Display rich formatted text + category: blocks + sdkBinding: + type: jsonSchema + blockType: rich_text + schema: + type: object + required: [type, elements] + properties: + type: + type: string + const: rich_text + elements: + type: array + description: Rich text elements (sections, lists, etc.) + block_id: + type: string + maxLength: 255 + + # INTERACTIVE ELEMENTS + + button: + name: Button Element + description: Interactive button for actions + category: elements + sdkBinding: + type: jsonSchema + elementType: button + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + schema: + type: object + required: [type, text, action_id] + properties: + type: + type: string + const: button + text: + $ref: "#/composition/text" + description: Button text (plain_text only, max 75 chars) + action_id: + type: string + description: Identifier for the action + maxLength: 255 + url: + type: string + format: uri + description: URL to open when clicked + maxLength: 3000 + value: + type: string + description: Value sent with interaction payload + maxLength: 2000 + style: + type: string + enum: [primary, danger] + description: Button style (primary=green, danger=red) + confirm: + $ref: "#/composition/confirm" + description: Confirmation dialog before action + accessibility_label: + type: string + description: Label for screen readers + variants: + - default + - primary + - danger + accessibility: + keyboardSupport: true + screenReaderSupport: true + labelRequired: true + + static_select: + name: Static Select Menu + description: Drop-down menu with static options + category: elements + sdkBinding: + type: jsonSchema + elementType: static_select + webStandardMapping: + htmlElement: select + ariaRole: listbox + semanticType: input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: static_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + description: Placeholder text (plain_text only) + options: + type: array + description: List of options + maxItems: 100 + items: + $ref: "#/composition/option" + option_groups: + type: array + description: Grouped options + maxItems: 100 + items: + $ref: "#/composition/option_group" + initial_option: + $ref: "#/composition/option" + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + accessibility: + keyboardSupport: true + screenReaderSupport: true + + external_select: + name: External Data Select Menu + description: Select menu with options loaded from external source + category: elements + sdkBinding: + type: jsonSchema + elementType: external_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: external_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_option: + $ref: "#/composition/option" + min_query_length: + type: integer + description: Min characters before querying + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + + users_select: + name: User Select Menu + description: Select menu for choosing Slack users + category: elements + sdkBinding: + type: jsonSchema + elementType: users_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: users_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_user: + type: string + description: Initially selected user ID + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + + conversations_select: + name: Conversation Select Menu + description: Select menu for choosing conversations + category: elements + sdkBinding: + type: jsonSchema + elementType: conversations_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: conversations_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_conversation: + type: string + default_to_current_conversation: + type: boolean + confirm: + $ref: "#/composition/confirm" + response_url_enabled: + type: boolean + filter: + $ref: "#/composition/conversation_filter" + focus_on_load: + type: boolean + + channels_select: + name: Channel Select Menu + description: Select menu for choosing channels + category: elements + sdkBinding: + type: jsonSchema + elementType: channels_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: channels_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_channel: + type: string + confirm: + $ref: "#/composition/confirm" + response_url_enabled: + type: boolean + focus_on_load: + type: boolean + + multi_static_select: + name: Multi-Select Static Menu + description: Multi-select menu with static options + category: elements + sdkBinding: + type: jsonSchema + elementType: multi_static_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: multi_static_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + options: + type: array + maxItems: 100 + items: + $ref: "#/composition/option" + option_groups: + type: array + items: + $ref: "#/composition/option_group" + initial_options: + type: array + items: + $ref: "#/composition/option" + confirm: + $ref: "#/composition/confirm" + max_selected_items: + type: integer + focus_on_load: + type: boolean + + multi_external_select: + name: Multi-Select External Menu + description: Multi-select with external data source + category: elements + sdkBinding: + type: jsonSchema + elementType: multi_external_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: multi_external_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + min_query_length: + type: integer + initial_options: + type: array + items: + $ref: "#/composition/option" + confirm: + $ref: "#/composition/confirm" + max_selected_items: + type: integer + focus_on_load: + type: boolean + + multi_users_select: + name: Multi-User Select Menu + description: Multi-select for Slack users + category: elements + sdkBinding: + type: jsonSchema + elementType: multi_users_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: multi_users_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_users: + type: array + items: + type: string + confirm: + $ref: "#/composition/confirm" + max_selected_items: + type: integer + focus_on_load: + type: boolean + + multi_conversations_select: + name: Multi-Conversation Select Menu + description: Multi-select for conversations + category: elements + sdkBinding: + type: jsonSchema + elementType: multi_conversations_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: multi_conversations_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_conversations: + type: array + items: + type: string + default_to_current_conversation: + type: boolean + confirm: + $ref: "#/composition/confirm" + max_selected_items: + type: integer + filter: + $ref: "#/composition/conversation_filter" + focus_on_load: + type: boolean + + multi_channels_select: + name: Multi-Channel Select Menu + description: Multi-select for channels + category: elements + sdkBinding: + type: jsonSchema + elementType: multi_channels_select + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: multi_channels_select + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_channels: + type: array + items: + type: string + confirm: + $ref: "#/composition/confirm" + max_selected_items: + type: integer + focus_on_load: + type: boolean + + overflow: + name: Overflow Menu + description: Menu with overflow options (ellipsis menu) + category: elements + sdkBinding: + type: jsonSchema + elementType: overflow + webStandardMapping: + ariaRole: menu + semanticType: action + schema: + type: object + required: [type, action_id, options] + properties: + type: + type: string + const: overflow + action_id: + type: string + maxLength: 255 + options: + type: array + description: Menu options + minItems: 1 + maxItems: 5 + items: + $ref: "#/composition/option" + confirm: + $ref: "#/composition/confirm" + + datepicker: + name: Date Picker + description: Calendar-based date selection + category: elements + sdkBinding: + type: jsonSchema + elementType: datepicker + webStandardMapping: + htmlElement: input + inputType: date + semanticType: input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: datepicker + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_date: + type: string + format: date + description: Initial date in YYYY-MM-DD format + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + accessibility: + keyboardSupport: true + screenReaderSupport: true + + timepicker: + name: Time Picker + description: Time selection input + category: elements + sdkBinding: + type: jsonSchema + elementType: timepicker + webStandardMapping: + htmlElement: input + inputType: time + semanticType: input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: timepicker + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_time: + type: string + description: Initial time in HH:mm format + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + timezone: + type: string + description: IANA timezone + + datetimepicker: + name: Date Time Picker + description: Combined date and time selection + category: elements + sdkBinding: + type: jsonSchema + elementType: datetimepicker + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: datetimepicker + action_id: + type: string + maxLength: 255 + initial_date_time: + type: integer + description: Unix timestamp + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + + plain_text_input: + name: Plain Text Input + description: Single or multi-line text input + category: elements + sdkBinding: + type: jsonSchema + elementType: plain_text_input + webStandardMapping: + htmlElement: input + inputType: text + semanticType: input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: plain_text_input + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_value: + type: string + multiline: + type: boolean + description: Enable multi-line input + min_length: + type: integer + description: Minimum length + max_length: + type: integer + description: Maximum length + dispatch_action_config: + $ref: "#/composition/dispatch_action_config" + focus_on_load: + type: boolean + accessibility: + keyboardSupport: true + screenReaderSupport: true + + email_text_input: + name: Email Text Input + description: Email address input with validation + category: elements + sdkBinding: + type: jsonSchema + elementType: email_text_input + webStandardMapping: + htmlElement: input + inputType: email + semanticType: input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: email_text_input + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_value: + type: string + format: email + dispatch_action_config: + $ref: "#/composition/dispatch_action_config" + focus_on_load: + type: boolean + + url_text_input: + name: URL Text Input + description: URL input with validation + category: elements + sdkBinding: + type: jsonSchema + elementType: url_text_input + webStandardMapping: + htmlElement: input + inputType: url + semanticType: input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: url_text_input + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_value: + type: string + format: uri + dispatch_action_config: + $ref: "#/composition/dispatch_action_config" + focus_on_load: + type: boolean + + number_input: + name: Number Input + description: Numeric input with validation + category: elements + sdkBinding: + type: jsonSchema + elementType: number_input + webStandardMapping: + htmlElement: input + inputType: number + semanticType: input + schema: + type: object + required: [type, action_id, is_decimal_allowed] + properties: + type: + type: string + const: number_input + action_id: + type: string + maxLength: 255 + is_decimal_allowed: + type: boolean + description: Allow decimal numbers + placeholder: + $ref: "#/composition/text" + initial_value: + type: string + description: Initial numeric value as string + min_value: + type: string + description: Minimum value + max_value: + type: string + description: Maximum value + dispatch_action_config: + $ref: "#/composition/dispatch_action_config" + focus_on_load: + type: boolean + + checkboxes: + name: Checkboxes + description: Checkbox group for multiple selections + category: elements + sdkBinding: + type: jsonSchema + elementType: checkboxes + webStandardMapping: + htmlElement: input + inputType: checkbox + ariaRole: group + semanticType: input + schema: + type: object + required: [type, action_id, options] + properties: + type: + type: string + const: checkboxes + action_id: + type: string + maxLength: 255 + options: + type: array + description: Checkbox options + minItems: 1 + maxItems: 10 + items: + $ref: "#/composition/option" + initial_options: + type: array + description: Pre-selected options + items: + $ref: "#/composition/option" + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + accessibility: + keyboardSupport: true + screenReaderSupport: true + + radio_buttons: + name: Radio Buttons + description: Radio button group for single selection + category: elements + sdkBinding: + type: jsonSchema + elementType: radio_buttons + webStandardMapping: + htmlElement: input + inputType: radio + ariaRole: radiogroup + semanticType: input + schema: + type: object + required: [type, action_id, options] + properties: + type: + type: string + const: radio_buttons + action_id: + type: string + maxLength: 255 + options: + type: array + description: Radio options + minItems: 1 + maxItems: 10 + items: + $ref: "#/composition/option" + initial_option: + $ref: "#/composition/option" + confirm: + $ref: "#/composition/confirm" + focus_on_load: + type: boolean + accessibility: + keyboardSupport: true + screenReaderSupport: true + + rich_text_input: + name: Rich Text Input + description: Rich text editor with formatting + category: elements + sdkBinding: + type: jsonSchema + elementType: rich_text_input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: rich_text_input + action_id: + type: string + maxLength: 255 + placeholder: + $ref: "#/composition/text" + initial_value: + type: object + description: Initial rich text value + dispatch_action_config: + $ref: "#/composition/dispatch_action_config" + focus_on_load: + type: boolean + + file_input: + name: File Input + description: File upload input + category: elements + sdkBinding: + type: jsonSchema + elementType: file_input + schema: + type: object + required: [type, action_id] + properties: + type: + type: string + const: file_input + action_id: + type: string + maxLength: 255 + filetypes: + type: array + description: Allowed file extensions + items: + type: string + max_files: + type: integer + description: Maximum number of files + minimum: 1 + maximum: 10 + + # COMPOSITION OBJECTS + + text: + name: Text Object + description: Text with plain_text or mrkdwn formatting + category: composition + schema: + type: object + required: [type, text] + properties: + type: + type: string + enum: [plain_text, mrkdwn] + text: + type: string + maxLength: 3000 + emoji: + type: boolean + description: Escape emoji codes (plain_text only) + verbatim: + type: boolean + description: Disable auto-linking (mrkdwn only) + + option: + name: Option Object + description: Single option for select menus and overflow menus + category: composition + schema: + type: object + required: [text, value] + properties: + text: + $ref: "#/composition/text" + description: Option text (plain_text only, max 75 chars) + value: + type: string + description: Option value + maxLength: 75 + description: + $ref: "#/composition/text" + description: Detailed description (plain_text, max 75 chars) + url: + type: string + format: uri + description: URL loaded when option selected + + option_group: + name: Option Group + description: Group of options with a label + category: composition + schema: + type: object + required: [label, options] + properties: + label: + $ref: "#/composition/text" + description: Group label (plain_text only, max 75 chars) + options: + type: array + description: Options in the group + maxItems: 100 + items: + $ref: "#/composition/option" + + confirm: + name: Confirmation Dialog + description: Confirmation prompt before destructive actions + category: composition + schema: + type: object + required: [title, text, confirm, deny] + properties: + title: + $ref: "#/composition/text" + description: Dialog title (plain_text only, max 100 chars) + text: + $ref: "#/composition/text" + description: Confirmation message (max 300 chars) + confirm: + $ref: "#/composition/text" + description: Confirm button text (plain_text, max 30 chars) + deny: + $ref: "#/composition/text" + description: Deny button text (plain_text, max 30 chars) + style: + type: string + enum: [primary, danger] + description: Confirm button style + + conversation_filter: + name: Conversation Filter + description: Filter for conversation lists + category: composition + schema: + type: object + properties: + include: + type: array + description: Conversation types to include + items: + type: string + enum: [im, mpim, private, public] + exclude_external_shared_channels: + type: boolean + exclude_bot_users: + type: boolean + + dispatch_action_config: + name: Dispatch Action Config + description: Configuration for dispatching actions on input change + category: composition + schema: + type: object + properties: + trigger_actions_on: + type: array + description: When to trigger actions + items: + type: string + enum: [on_enter_pressed, on_character_entered] + +policies: + componentRequirement: + level: required + scope: all + rationale: | + Slack enforces exclusive use of Block Kit blocks and elements. + No custom UI components are allowed - all interfaces must be + built using the provided Block Kit JSON structure. + + customComponents: + allowed: false + documentation: https://api.slack.com/block-kit + constraints: + - All UI must be defined using Block Kit JSON + - No custom HTML, CSS, or JavaScript + - Apps execute server-side; UI is rendered by Slack client + rationale: | + Block Kit ensures consistent user experience, accessibility, + security, and cross-platform compatibility across all Slack clients. + + publishing: + workspace: + name: Workspace Apps + componentRequirement: required + customComponentsAllowed: false + reviewRequired: false + notes: | + Apps installed to a single workspace. Block Kit required + but no review process for private installations. + + publicDistribution: + name: Public Distribution + componentRequirement: required + customComponentsAllowed: false + reviewRequired: true + securityReviewRequired: true + notes: | + Apps distributed publicly undergo App Directory review + including security, functionality, and UX assessment. + + appDirectory: + name: Slack App Directory + componentRequirement: required + customComponentsAllowed: false + certificationRequired: false + reviewRequired: true + securityReviewRequired: true + notes: | + Listing in App Directory requires passing review. + Featured apps undergo additional vetting. + + designGuidelines: + required: true + designSystem: Block Kit + designSystemUrl: https://api.slack.com/block-kit + builderUrl: https://app.slack.com/block-kit-builder + designTokensProvided: false + guidelines: + - Use Block Kit Builder to design and validate layouts + - Follow text length limits for each block type + - Provide clear, concise labels and placeholder text + - Use confirmation dialogs for destructive actions + - Ensure accessibility with alt text and labels + + performance: + messageBlockLimit: 50 + modalBlockLimit: 100 + homeTabBlockLimit: 100 + interactionTimeout: 3000 + notes: | + Interactions must respond within 3 seconds. Long-running + operations should use response URLs for async updates. + +extensionPoints: + - id: message + name: Messages + type: surface + extensionType: jsonResponse + description: | + Block Kit messages in channels, DMs, or threads. The primary + surface for rich app interactions in conversations. + supportedBlocks: + - section + - divider + - image + - actions + - context + - header + - video + - file + - rich_text + constraints: + maxBlocks: 50 + maxTextLength: 3000 + supportsMarkdown: true + context: + provides: + - channel_id + - user_id + - team_id + - message_ts + - thread_ts + actions: + - postMessage + - updateMessage + - postEphemeral + documentation: https://api.slack.com/surfaces/messages + + - id: modal + name: Modals + type: surface + extensionType: jsonResponse + description: | + Focused surfaces for data collection, confirmations, and + workflows. Opened via views.open API call. + supportedBlocks: + - section + - divider + - image + - actions + - context + - input + - header + - video + - rich_text + constraints: + maxBlocks: 100 + maxInputBlocks: 100 + canStack: true + maxStackDepth: 3 + context: + provides: + - trigger_id + - user_id + - team_id + - view_id + actions: + - viewsOpen + - viewsUpdate + - viewsPush + callbacks: + - view_submission + - view_closed + documentation: https://api.slack.com/surfaces/modals + + - id: home-tab + name: App Home Tab + type: surface + extensionType: jsonResponse + description: | + Personal space for users to interact with your app. + Accessed via the app's Home tab. + supportedBlocks: + - section + - divider + - image + - actions + - context + - header + - video + - rich_text + constraints: + maxBlocks: 100 + noInputBlocks: true + refreshable: true + context: + provides: + - user_id + - team_id + - view_id + actions: + - viewsPublish + callbacks: + - app_home_opened + documentation: https://api.slack.com/surfaces/app-home + + - id: workflow-step + name: Workflow Steps + type: surface + extensionType: jsonResponse + description: | + Custom steps in Workflow Builder. Includes configuration + modal and execution logic. + supportedBlocks: + - section + - divider + - actions + - context + - input + - header + constraints: + configurationRequired: true + executionAsync: true + context: + provides: + - workflow_step_id + - inputs + - outputs + actions: + - workflowStepEdit + - workflowsUpdateStep + callbacks: + - workflow_step_edit + - workflow_step_execute + documentation: https://api.slack.com/workflows/steps + +renderingEngines: + slack-native: + type: native + name: Slack Native Rendering + description: | + Block Kit is rendered natively by Slack clients (desktop, mobile, web). + Apps define UI as JSON; Slack handles all rendering and interactions. + sandboxing: + serverSideExecution: true + clientSideExecution: false + notes: | + App logic runs on developer servers. Slack clients send + interaction payloads to registered endpoints. + platforms: + - Slack Desktop (Windows, macOS, Linux) + - Slack Mobile (iOS, Android) + - Slack Web + +jsonFormsIntegration: + supported: false + notes: | + Block Kit has its own input/form system with the input block + and various input elements. Not compatible with JSON Forms. + +mcpAppsIntegration: + supported: false + notes: Not yet integrated with MCP Apps specification + +extensionType: jsonResponse + +extensions: + declarativeSchemas: + enabled: true + schemaFormat: json + description: | + Block Kit is entirely JSON-based. Apps construct blocks and + elements as JSON objects conforming to Block Kit schemas. + validation: + builderTool: https://app.slack.com/block-kit-builder + sdkValidation: true + runtimeValidation: true + schemaDocumentation: https://api.slack.com/reference/block-kit/blocks + + i18n: + enabled: true + localeDetection: automatic + description: | + Slack provides user locale information. Apps can localize + Block Kit text content based on user preferences. + implementation: + clientProvides: + - user_locale + - team_locale + developerResponsibility: + - Translate text objects + - Handle RTL languages + - Format dates/times appropriately + supportedLocales: + - en-US + - en-GB + - de-DE + - es-ES + - es-LA + - fr-FR + - it-IT + - ja-JP + - ko-KR + - pt-BR + - ru-RU + - zh-CN + - zh-TW + documentation: https://api.slack.com/reference/internationalization + + compliance: + enabled: true + description: | + Apps distributed publicly must comply with Slack's App + Directory Review requirements and security standards. + requirements: + securityReview: + required: true + scope: publicDistribution + includes: + - Data handling and privacy review + - OAuth implementation verification + - Secure API usage patterns + - Permission scope audit + functionalReview: + required: true + scope: appDirectory + includes: + - App functionality testing + - Error handling validation + - User experience assessment + contentReview: + required: true + scope: appDirectory + includes: + - App listing content + - Screenshots and media + - Privacy policy and terms + certifications: + dataResidency: + available: true + description: Data Residency certification for regulated industries + enterpriseKeyManagement: + available: true + description: EKM support for enterprise customers + documentation: https://api.slack.com/start/distributing/directory + privacyPolicy: https://slack.com/privacy-policy + + analytics: + enabled: true + description: | + Slack provides analytics for app usage, installations, + and user engagement within the Slack platform. + metrics: + - Daily/Monthly Active Users + - Message interactions + - Modal opens and submissions + - App Home views + - Installation/uninstallation rates + dashboard: https://api.slack.com/apps (App Management) + + testing: + enabled: true + description: Tools and methods for testing Block Kit interfaces + tools: + blockKitBuilder: + url: https://app.slack.com/block-kit-builder + description: Visual builder with live preview and validation + features: + - Visual block composition + - JSON export/import + - Sample payload generation + - Validation errors + slackPlatformSimulator: + description: Test apps in development workspace + features: + - Real-time interaction testing + - Event simulation + - Permission testing + documentation: https://api.slack.com/block-kit/building + + accessibilityFeatures: + keyboardNavigation: true + screenReaderSupport: true + highContrastMode: true + description: | + Block Kit is designed with accessibility built-in. Slack + clients handle keyboard navigation, screen reader support, + and high contrast modes automatically. + guidelines: + - Provide alt text for all images + - Use descriptive button labels + - Include accessibility_label for complex elements + - Ensure logical focus order in modals + documentation: https://api.slack.com/block-kit/accessibility + + rateLimits: + description: Rate limits for Slack API methods + limits: + chatPostMessage: + tier1: 1 per second + tier2: 20 per minute + tier3: 50+ per minute (varies by workspace) + viewsOpen: + rate: 3 per second per user + viewsUpdate: + rate: 3 per second per view + viewsPublish: + rate: 5 per minute per user + documentation: https://api.slack.com/docs/rate-limits + + securityFeatures: + oauthRequired: true + scopedPermissions: true + requestSigning: true + description: | + Slack apps use OAuth 2.0 for authentication with granular + permission scopes. All requests are signed and verified. + features: + - Request signature verification + - Token rotation support + - App-level tokens + - User tokens vs bot tokens + - Workspace app management + documentation: https://api.slack.com/authentication + +notes: | + Slack Block Kit is a comprehensive, JSON-based UI framework that enforces + a strict component model. Apps cannot use custom UI components - all + interfaces must be built using Block Kit's declarative structure. + + Key characteristics: + - Fully declarative: UI defined as JSON, not code + - Server-side execution: App logic runs on developer servers + - Native rendering: Slack clients render Block Kit natively + - Cross-platform: Consistent across desktop, mobile, and web + - Accessibility built-in: Keyboard, screen reader support automatic + - Interactive: Rich interactions via action handlers + + Block Kit is used across all Slack surfaces: messages, modals, Home tabs, + and workflow steps. The Block Kit Builder provides visual design and + validation tools for developers. + +metadata: + fenestra: + createdAt: "2025-12-30" + author: "Fenestra Specification Team" + category: "Communication Platform" + tags: + - messaging + - collaboration + - json-ui + - declarative + - block-kit + relatedPlatforms: + - Microsoft Teams (Adaptive Cards) + - Discord (Embeds) + - Webex (Cards) diff --git a/specs/fenestra/examples/0.1.0/stripe.fenestra.yaml b/specs/fenestra/examples/0.1.0/stripe.fenestra.yaml new file mode 100644 index 0000000..b0e8399 --- /dev/null +++ b/specs/fenestra/examples/0.1.0/stripe.fenestra.yaml @@ -0,0 +1,1033 @@ +# Fenestra Document: Stripe Elements +# +# Stripe Elements represents an embeddedSdk extension type - pre-built UI components +# that developers embed in their websites for secure payment collection. +# +# Key characteristics: +# - SDK MUST be loaded from Stripe's CDN (cannot be bundled) +# - Handles PCI compliance automatically +# - Extensive customization via Appearance API +# - Components integrate seamlessly into merchant checkout pages + +fenestra: "0.1.0" + +info: + title: Stripe Elements UI Ecosystem + version: "1.0.0" + description: | + Stripe Elements is a set of pre-built UI components for securely collecting + payment information on the web. Elements are designed to be embedded in + merchant checkout pages and handle the complex requirements of payment security. + + Stripe.js and Elements provide: + - PCI DSS Level 1 compliant payment collection + - Automatic card validation and formatting + - Support for 40+ payment methods + - Dynamic localization for 40+ languages + - Real-time error handling and validation + - Extensive styling and theming capabilities + + Security Model: Payment data never touches merchant servers. Elements communicate + directly with Stripe, significantly reducing PCI compliance scope. + +platform: + name: Stripe + vendor: Stripe, Inc. + documentation: https://stripe.com/docs + appMarketplace: https://marketplace.stripe.com/ + +# ============================================================================= +# SDK DEFINITIONS +# ============================================================================= + +sdks: + stripe-js: + name: Stripe.js + packageManager: npm + package: "@stripe/stripe-js" + version: "^2.0.0" + platform: web + documentation: https://stripe.com/docs/js + repository: https://github.com/stripe/stripe-js + cdn: https://js.stripe.com/v3/ + cdnRequired: true + installCommand: npm install @stripe/stripe-js + exports: + loadStripe: + type: utility + description: Loads Stripe.js asynchronously from CDN + Stripe: + type: utility + description: Main Stripe.js instance for creating Elements + + react-stripe-js: + name: React Stripe.js + packageManager: npm + package: "@stripe/react-stripe-js" + version: "^2.0.0" + platform: web + documentation: https://stripe.com/docs/stripe-js/react + repository: https://github.com/stripe/react-stripe-js + installCommand: npm install @stripe/react-stripe-js @stripe/stripe-js + exports: + # Provider Components + Elements: + type: component + description: Provider component that wraps all Stripe Elements + # Element Components + PaymentElement: + type: component + description: All-in-one payment method collection component + CardElement: + type: component + description: Complete card input (number, expiry, CVC) + CardNumberElement: + type: component + description: Card number input only + CardExpiryElement: + type: component + description: Card expiry date input only + CardCvcElement: + type: component + description: Card CVC input only + ExpressCheckoutElement: + type: component + description: One-click payment buttons (Apple Pay, Google Pay, etc.) + LinkAuthenticationElement: + type: component + description: Email input with Link autofill + AddressElement: + type: component + description: Complete address collection form + PaymentMethodMessagingElement: + type: component + description: Marketing messages for payment methods (BNPL, etc.) + IbanElement: + type: component + description: IBAN input for SEPA Direct Debit + IdealBankElement: + type: component + description: iDEAL bank selection + AuBankAccountElement: + type: component + description: Australian bank account input + # Hooks + useStripe: + type: hook + description: Hook to access Stripe instance + useElements: + type: hook + description: Hook to access Elements instance + + stripe-ios: + name: Stripe iOS SDK + packageManager: cocoapods + package: Stripe + version: "^23.0.0" + platform: ios + documentation: https://stripe.com/docs/mobile/ios + repository: https://github.com/stripe/stripe-ios + installCommand: pod 'Stripe' + mobile: + minOsVersion: "13.0" + targetOsVersion: "17.0" + architectures: [arm64, x86_64] + appStoreGuidelines: https://stripe.com/docs/security/guide#app-store + + stripe-android: + name: Stripe Android SDK + packageManager: gradle + package: com.stripe:stripe-android + version: "^20.0.0" + platform: android + documentation: https://stripe.com/docs/mobile/android + repository: https://github.com/stripe/stripe-android + installCommand: implementation 'com.stripe:stripe-android:20.+' + mobile: + minOsVersion: "5.0" + targetOsVersion: "14.0" + + stripe-react-native: + name: Stripe React Native SDK + packageManager: npm + package: "@stripe/stripe-react-native" + version: "^0.35.0" + platform: react-native + documentation: https://stripe.com/docs/mobile/react-native + repository: https://github.com/stripe/stripe-react-native + installCommand: npm install @stripe/stripe-react-native + +# ============================================================================= +# COMPONENT CATALOG +# ============================================================================= + +componentCatalog: + categories: + payment: + name: Payment Collection + description: Components for collecting payment information + components: + - PaymentElement + - CardElement + - CardNumberElement + - CardExpiryElement + - CardCvcElement + - IbanElement + - IdealBankElement + - AuBankAccountElement + + express: + name: Express Checkout + description: One-click payment experiences + components: + - ExpressCheckoutElement + + identity: + name: Identity & Authentication + description: User identification and Link integration + components: + - LinkAuthenticationElement + + address: + name: Address Collection + description: Shipping and billing address forms + components: + - AddressElement + + messaging: + name: Payment Messaging + description: Marketing and informational messages + components: + - PaymentMethodMessagingElement + + components: + PaymentElement: + name: Payment Element + description: | + All-in-one component that dynamically displays relevant payment methods + based on transaction amount, currency, and customer location. Recommended + for most integrations as it automatically adapts to customer preferences. + category: payment + sdkBinding: + sdk: react-stripe-js + export: PaymentElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: div + ariaRole: group + semanticType: input + props: + type: object + properties: + options: + type: object + properties: + layout: + type: string + enum: [tabs, accordion, auto] + default: auto + description: How to display multiple payment methods + business: + type: object + description: Business name shown to customers + fields: + type: object + properties: + billingDetails: + type: string + enum: [auto, never] + description: Whether to collect billing details + wallets: + type: object + properties: + applePay: + type: string + enum: [auto, never] + googlePay: + type: string + enum: [auto, never] + readOnly: + type: boolean + default: false + onChange: + type: function + description: Callback when payment method state changes + onReady: + type: function + description: Callback when component is fully loaded + onFocus: + type: function + onBlur: + type: function + events: + change: + description: Payment method or validation state changed + payload: + type: object + properties: + complete: + type: boolean + value: + type: object + ready: + description: Component fully loaded and ready + focus: + description: Component received focus + blur: + description: Component lost focus + accessibility: + keyboardSupport: true + screenReaderSupport: true + focusManagement: Automatic focus management within multi-field component + notes: | + Stripe Elements are built with accessibility in mind, including + proper ARIA labels, keyboard navigation, and screen reader support. + examples: + - title: Basic Payment Element + code: | + import { PaymentElement } from '@stripe/react-stripe-js'; + + function CheckoutForm() { + return ( +
+ + + + ); + } + language: jsx + - title: Payment Element with Options + code: | + { + if (event.complete) { + console.log('Payment method ready'); + } + }} + /> + language: jsx + + CardElement: + name: Card Element + description: | + Single-line card input that collects card number, expiry date, and CVC. + Provides automatic formatting, validation, and card brand detection. + category: payment + sdkBinding: + sdk: react-stripe-js + export: CardElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: div + ariaRole: group + semanticType: input + props: + type: object + properties: + options: + type: object + properties: + hidePostalCode: + type: boolean + default: false + iconStyle: + type: string + enum: [solid, default] + disabled: + type: boolean + default: false + onChange: + type: function + onReady: + type: function + onFocus: + type: function + onBlur: + type: function + events: + change: + description: Card input state changed + payload: + type: object + properties: + complete: + type: boolean + brand: + type: string + description: "Card brand: visa, mastercard, amex, etc." + error: + type: object + accessibility: + keyboardSupport: true + screenReaderSupport: true + focusManagement: Single tab stop with internal field navigation + examples: + - title: Basic Card Element + code: | + import { CardElement } from '@stripe/react-stripe-js'; + + { + console.log('Brand:', event.brand); + if (event.error) { + console.error(event.error.message); + } + }} + /> + language: jsx + + ExpressCheckoutElement: + name: Express Checkout Element + description: | + Displays one-click payment buttons (Apple Pay, Google Pay, Link, etc.) + based on customer device and saved payment methods. Automatically handles + eligibility and payment sheet presentation. + category: express + sdkBinding: + sdk: react-stripe-js + export: ExpressCheckoutElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: div + ariaRole: button + semanticType: action + props: + type: object + properties: + options: + type: object + properties: + buttonType: + type: object + properties: + applePay: + type: string + enum: [plain, buy, donate, check-out, book, subscribe] + googlePay: + type: string + enum: [buy, donate, plain, book, checkout, subscribe, pay] + buttonTheme: + type: object + properties: + applePay: + type: string + enum: [black, white, white-outline] + googlePay: + type: string + enum: [black, white] + buttonHeight: + type: string + description: CSS height value (e.g., "48px") + onConfirm: + type: function + description: Called when customer authorizes payment + onClick: + type: function + description: Called when button is clicked + examples: + - title: Express Checkout Element + code: | + import { ExpressCheckoutElement } from '@stripe/react-stripe-js'; + + { + // Handle payment confirmation + const { error } = await stripe.confirmPayment({ + elements, + confirmParams: { return_url: '...' } + }); + }} + /> + language: jsx + + LinkAuthenticationElement: + name: Link Authentication Element + description: | + Email input with Link integration. Allows returning customers to + autofill their payment details with a simple OTP verification. + category: identity + sdkBinding: + sdk: react-stripe-js + export: LinkAuthenticationElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: input + ariaRole: textbox + semanticType: input + props: + type: object + properties: + options: + type: object + properties: + defaultValues: + type: object + properties: + email: + type: string + onChange: + type: function + examples: + - title: Link Authentication Element + code: | + import { LinkAuthenticationElement } from '@stripe/react-stripe-js'; + + { + console.log('Email:', event.value.email); + }} + /> + language: jsx + + AddressElement: + name: Address Element + description: | + Complete address collection form with automatic postal code lookup, + address validation, and international format support. Adapts fields + based on selected country. + category: address + sdkBinding: + sdk: react-stripe-js + export: AddressElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: div + ariaRole: group + semanticType: input + props: + type: object + properties: + options: + type: object + properties: + mode: + type: string + enum: [shipping, billing] + description: Determines required fields + allowedCountries: + type: array + items: + type: string + description: ISO country codes + autocomplete: + type: object + properties: + mode: + type: string + enum: [automatic, google_maps_api, disabled] + defaultValues: + type: object + properties: + name: + type: string + address: + type: object + fields: + type: object + properties: + phone: + type: string + enum: [always, auto, never] + onChange: + type: function + examples: + - title: Shipping Address Element + code: | + import { AddressElement } from '@stripe/react-stripe-js'; + + { + if (event.complete) { + console.log('Address:', event.value.address); + } + }} + /> + language: jsx + + PaymentMethodMessagingElement: + name: Payment Method Messaging Element + description: | + Displays promotional messaging for payment methods like "Pay in 4 + interest-free installments" for Buy Now, Pay Later options. + category: messaging + sdkBinding: + sdk: react-stripe-js + export: PaymentMethodMessagingElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: div + ariaRole: region + semanticType: display + props: + type: object + properties: + options: + type: object + properties: + amount: + type: number + description: Amount in cents + currency: + type: string + paymentMethodTypes: + type: array + items: + type: string + countryCode: + type: string + examples: + - title: Afterpay Messaging + code: | + import { PaymentMethodMessagingElement } from '@stripe/react-stripe-js'; + + + language: jsx + + IbanElement: + name: IBAN Element + description: | + IBAN input for SEPA Direct Debit payments. Automatically validates + IBAN format and displays supported country codes. + category: payment + sdkBinding: + sdk: react-stripe-js + export: IbanElement + importPath: "@stripe/react-stripe-js" + webStandardMapping: + htmlElement: input + ariaRole: textbox + semanticType: input + props: + type: object + properties: + options: + type: object + properties: + supportedCountries: + type: array + items: + type: string + placeholderCountry: + type: string + examples: + - title: SEPA Direct Debit + code: | + import { IbanElement } from '@stripe/react-stripe-js'; + + + language: jsx + +# ============================================================================= +# EXTENSION POINTS +# ============================================================================= + +extensionPoints: + - id: merchant-checkout-page + name: Merchant Checkout Page + type: embedded + extensionType: embeddedSdk + description: | + Stripe Elements are embedded directly into merchant checkout pages. + The SDK creates secure iframe-based inputs that merchants style and + position within their own page layout. Payment data flows directly + from the customer's browser to Stripe without touching merchant servers. + + extensionTypeConfig: + sdk: + package: "@stripe/stripe-js" + cdn: https://js.stripe.com/v3/ + cdnRequired: true + + mountPattern: domSelector + + theming: + system: Appearance API + customizable: true + variables: + - theme + - variables.colorPrimary + - variables.colorBackground + - variables.colorText + - variables.colorDanger + - variables.fontFamily + - variables.spacingUnit + - variables.borderRadius + - variables.fontSizeBase + - variables.fontSizeSm + - variables.fontSizeXs + - rules (CSS-like object) + prebuiltThemes: + - stripe + - night + - flat + - none + + communication: + pattern: promises + events: + - ready + - change + - focus + - blur + - escape + - networkerror + + supportedComponents: + - PaymentElement + - CardElement + - CardNumberElement + - CardExpiryElement + - CardCvcElement + - ExpressCheckoutElement + - LinkAuthenticationElement + - AddressElement + - PaymentMethodMessagingElement + - IbanElement + - IdealBankElement + - AuBankAccountElement + + constraints: + responsive: true + + context: + provides: + - publishableKey + - clientSecret + - customer + - locale + actions: + - createPaymentMethod + - confirmPayment + - confirmSetup + - handleCardAction + - retrievePaymentIntent + - retrieveSetupIntent + + - id: mobile-checkout + name: Mobile Native Checkout + type: embedded + extensionType: embeddedSdk + description: | + Native mobile SDKs for iOS and Android provide pre-built UI components + for payment collection with platform-native look and feel. + + extensionTypeConfig: + sdk: + package: Stripe + cdnRequired: false + + mountPattern: function + + theming: + system: Platform Native + customizable: true + variables: + - primaryBackgroundColor + - secondaryBackgroundColor + - primaryForegroundColor + - secondaryForegroundColor + - accentColor + - errorColor + - font + + communication: + pattern: callbacks + events: + - didChange + - didFinish + - didFail + + supportedComponents: + - PaymentSheet + - CardForm + - ApplePayButton + - GooglePayButton + + context: + provides: + - publishableKey + - ephemeralKey + - customer + - paymentIntent + actions: + - presentPaymentSheet + - confirmPayment + - createPaymentMethod + +# ============================================================================= +# POLICIES +# ============================================================================= + +policies: + componentRequirement: + level: required + scope: all + rationale: | + Stripe Elements components MUST be used for payment data collection + to maintain PCI DSS Level 1 compliance. Payment data never touches + merchant servers - it flows directly from Elements to Stripe. + + This requirement is non-negotiable for security and compliance reasons. + + customComponents: + allowed: false + constraints: + - Merchants cannot create custom payment input fields + - All payment data collection must use Stripe Elements + - Styling is allowed via Appearance API only + documentation: https://stripe.com/docs/security/guide + + publishing: + allIntegrations: + componentRequirement: required + customComponentsAllowed: false + reviewRequired: false + notes: | + All Stripe integrations, whether using publishable or restricted keys, + must use Elements for payment collection. No exceptions. + + designGuidelines: + required: false + designSystem: "Appearance API" + designSystemUrl: https://stripe.com/docs/elements/appearance-api + designTokensProvided: true + + security: + cdnRequirement: + required: true + rationale: | + Stripe.js MUST be loaded from js.stripe.com CDN. Self-hosting or + bundling Stripe.js is prohibited for security reasons: + + 1. Stripe can push critical security updates instantly + 2. Version integrity is guaranteed + 3. PCI compliance is maintained + 4. TLS and certificate management is handled by Stripe + enforcement: Runtime validation + documentation: https://stripe.com/docs/security/guide#validating-pci-compliance + + pciCompliance: + level: PCI DSS Level 1 + scope: Stripe handles all payment data + merchantScope: SAQ A (minimal compliance burden) + documentation: https://stripe.com/docs/security + +# ============================================================================= +# RENDERING ENGINES +# ============================================================================= + +renderingEngines: + stripe-elements: + type: custom + name: Stripe Elements Renderer + description: | + Secure iframe-based rendering engine. Each Element component creates + an isolated iframe that communicates with the parent page via postMessage. + This ensures payment data never touches the merchant's JavaScript context. + + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + cspPolicy: | + Merchants must allow https://js.stripe.com in their CSP: + script-src https://js.stripe.com; + frame-src https://js.stripe.com; + connect-src https://api.stripe.com; + + react-renderer: + type: react + name: React Stripe.js + description: | + React wrapper components that manage Element lifecycle and provide + idiomatic React patterns (hooks, context, etc.) while maintaining + the same security model as vanilla Stripe.js. + +# ============================================================================= +# EXTENSIONS +# ============================================================================= + +x-compliance: + security: + platformCertifications: + - PCI DSS Level 1 + - SOC 2 Type II + - ISO 27001 + extensionRequirements: + httpsOnly: true + cspCompliance: true + noInlineScripts: true + noExternalScripts: false + securityReview: + required: false + scope: none + dataHandling: + piiAllowed: true + piiMustEncrypt: true + dataRetentionPolicy: none + documentation: https://stripe.com/docs/security + + privacy: + platformCompliance: + gdpr: true + ccpa: true + dataResidency: + available: true + regions: + - US + - EU + - APAC + extensionRequirements: + privacyPolicyRequired: true + consentManagement: both + dataProcessingAgreement: required + userRights: + dataExportSupported: true + dataDeletionSupported: true + documentation: https://stripe.com/privacy + + sharedResponsibility: + platformHandles: + - Payment data collection and storage + - PCI DSS compliance + - Card tokenization + - Payment processing security + - Fraud detection (Stripe Radar) + - Strong Customer Authentication (SCA/3DS) + - Regional payment method support + developerHandles: + - HTTPS implementation on their domain + - User authentication and authorization + - Order/transaction data storage + - Privacy policy and terms of service + - User consent management + - Webhook signature verification + documentation: https://stripe.com/docs/security/guide + +x-i18n: + platformSupport: + enabled: true + availableLocales: + - ar # Arabic + - bg # Bulgarian + - cs # Czech + - da # Danish + - de # German + - el # Greek + - en # English + - en-GB # English (UK) + - es # Spanish + - es-419 # Spanish (Latin America) + - et # Estonian + - fi # Finnish + - fil # Filipino + - fr # French + - fr-CA # French (Canada) + - he # Hebrew + - hr # Croatian + - hu # Hungarian + - id # Indonesian + - it # Italian + - ja # Japanese + - ko # Korean + - lt # Lithuanian + - lv # Latvian + - ms # Malay + - mt # Maltese + - nb # Norwegian Bokmål + - nl # Dutch + - pl # Polish + - pt # Portuguese (Brazil) + - pt-BR # Portuguese (Brazil) + - ro # Romanian + - ru # Russian + - sk # Slovak + - sl # Slovenian + - sv # Swedish + - th # Thai + - tr # Turkish + - vi # Vietnamese + - zh # Chinese (Simplified) + - zh-HK # Chinese (Hong Kong) + - zh-TW # Chinese (Traditional) + localeDetection: + method: automatic + sources: + - stripe.elements({ locale: '...' }) option + - Accept-Language header + - Customer's saved preferences + rtlSupport: + enabled: true + languages: + - ar # Arabic + - he # Hebrew + + componentTranslations: + provided: true + scope: all + + developerRequirements: + translationMechanism: + format: json + bundleLocation: platform-hosted + marketplaceRequirement: + required: false + formatting: + dates: platform + numbers: platform + currencies: platform + + documentation: https://stripe.com/docs/js/appendix/supported_locales diff --git a/specs/fenestra/examples/0.1.0/teams.fenestra.yaml b/specs/fenestra/examples/0.1.0/teams.fenestra.yaml new file mode 100644 index 0000000..33920eb --- /dev/null +++ b/specs/fenestra/examples/0.1.0/teams.fenestra.yaml @@ -0,0 +1,1844 @@ +# Fenestra Document: Microsoft Teams Platform +# +# Microsoft Teams represents a hybrid extensibility model combining: +# 1. Adaptive Cards - Declarative JSON-based UI (like Slack Block Kit) +# 2. Tabs - Embedded web apps in sandboxed iframes +# 3. Bots - Conversational interfaces with Adaptive Card responses +# 4. Message Extensions - Search and action commands +# 5. Meeting Extensions - In-meeting experiences +# +# This specification documents both patterns: declarative (Adaptive Cards) +# and iframe-based (Tabs), plus the Teams JavaScript SDK for context and interaction. + +fenestra: "0.1.0" + +info: + title: Microsoft Teams App Platform + version: "1.24.0" + description: | + Microsoft Teams App Platform enables developers to build collaborative + experiences using a hybrid model of declarative UI and embedded web content. + + Key characteristics: + - Adaptive Cards: JSON-based declarative UI for bots and messages (REQUIRED) + - Tabs: Full web apps embedded in iframes with Teams context + - Bots: Conversational AI using Bot Framework + Adaptive Cards + - Message Extensions: Search/action commands extending compose box + - Meeting Extensions: In-meeting apps, stages, and panels + - Teams JS SDK: Bridge between iframe tabs and Teams context + + Teams apps work across Microsoft Teams, Outlook, and Microsoft 365 app. + + contact: + name: Microsoft Teams Platform Team + url: https://learn.microsoft.com/en-us/microsoftteams/platform/feedback + email: microsoftteamsdev@microsoft.com + +platform: + name: Microsoft Teams + vendor: Microsoft Corporation + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/ + appMarketplace: https://appsource.microsoft.com/en-us/marketplace/apps?product=teams + developerPortal: https://dev.teams.microsoft.com/ + changelog: https://learn.microsoft.com/en-us/microsoftteams/platform/whats-new + +sdks: + teams-js: + name: Microsoft Teams JavaScript SDK + packageManager: npm + package: "@microsoft/teams-js" + version: "^2.47.2" + repository: https://github.com/OfficeDev/microsoft-teams-library-js + documentation: https://learn.microsoft.com/en-us/javascript/api/overview/msteams-client + description: | + The TeamsJS library enables tabs (web pages) to access Teams context, + authenticate users, open dialogs, and interact with Teams capabilities. + Starting with v2.0, TeamsJS enables apps to run in Teams, Outlook, and + Microsoft 365 app. + exports: + app: + type: namespace + description: Core app initialization and context + authentication: + type: namespace + description: Authentication flows and token management + dialog: + type: namespace + description: Open dialogs and task modules + pages: + type: namespace + description: Page navigation and configuration + meeting: + type: namespace + description: Meeting-specific capabilities + chat: + type: namespace + description: Chat and channel interactions + calendar: + type: namespace + description: Calendar integration + + adaptivecards: + name: Adaptive Cards SDK + packageManager: npm + package: "adaptivecards" + version: "^3.0.4" + repository: https://github.com/microsoft/AdaptiveCards + documentation: https://learn.microsoft.com/en-us/adaptive-cards/sdk/rendering-cards/javascript/getting-started + description: | + JavaScript SDK for rendering Adaptive Cards. Used primarily for + previewing cards during development. In production, Teams/Outlook + render Adaptive Cards natively. + exports: + AdaptiveCard: + type: class + description: Adaptive Card renderer + HostConfig: + type: class + description: Host configuration for styling cards + Version: + type: utility + description: Schema version utilities + + botbuilder: + name: Microsoft Bot Framework SDK + packageManager: npm + package: "botbuilder" + version: "^4.22.3" + repository: https://github.com/microsoft/botbuilder-js + documentation: https://learn.microsoft.com/en-us/azure/bot-service/ + description: | + Bot Framework SDK for building conversational bots. Teams bots use + this SDK to handle messages, send Adaptive Cards, and respond to + user interactions. + exports: + BotFrameworkAdapter: + type: class + description: Adapter for Bot Framework protocol + TeamsActivityHandler: + type: class + description: Teams-specific bot handler + CardFactory: + type: utility + description: Factory for creating Adaptive Cards and other card types + MessageFactory: + type: utility + description: Factory for creating bot messages + +componentCatalog: + categories: + cardElements: + name: Adaptive Card Elements + description: Visual elements for displaying content in cards + components: + - TextBlock + - Image + - Media + - RichTextBlock + - Table + - FactSet + - ImageSet + + cardContainers: + name: Adaptive Card Containers + description: Layout containers for organizing card content + components: + - Container + - ColumnSet + - Column + - ActionSet + + cardInputs: + name: Adaptive Card Inputs + description: Form inputs for collecting user data + components: + - InputText + - InputNumber + - InputDate + - InputTime + - InputToggle + - InputChoiceSet + + cardActions: + name: Adaptive Card Actions + description: Interactive actions users can trigger + components: + - ActionSubmit + - ActionOpenUrl + - ActionShowCard + - ActionToggleVisibility + - ActionExecute + + components: + # ADAPTIVE CARD ELEMENTS + + TextBlock: + name: TextBlock + description: Display text with formatting options + category: cardElements + sdkBinding: + type: jsonSchema + elementType: TextBlock + webStandardMapping: + htmlElement: p + ariaRole: text + semanticType: display + schema: + type: object + required: [type, text] + properties: + type: + type: string + const: TextBlock + text: + type: string + description: Text content (supports Markdown subset) + color: + type: string + enum: [default, dark, light, accent, good, warning, attention] + fontType: + type: string + enum: [default, monospace] + size: + type: string + enum: [small, default, medium, large, extraLarge] + weight: + type: string + enum: [lighter, default, bolder] + isSubtle: + type: boolean + maxLines: + type: integer + description: Maximum lines before truncation + wrap: + type: boolean + description: Enable text wrapping + horizontalAlignment: + type: string + enum: [left, center, right] + id: + type: string + description: Unique element identifier + constraints: + supportsMarkdown: true + markdownSubset: basic + accessibility: + screenReaderSupport: true + + Image: + name: Image + description: Display an image + category: cardElements + sdkBinding: + type: jsonSchema + elementType: Image + webStandardMapping: + htmlElement: img + ariaRole: img + semanticType: media + schema: + type: object + required: [type, url] + properties: + type: + type: string + const: Image + url: + type: string + format: uri + description: Image URL (https required) + altText: + type: string + description: Alternative text for accessibility + backgroundColor: + type: string + description: Background color (hex) + size: + type: string + enum: [auto, stretch, small, medium, large] + style: + type: string + enum: [default, person] + description: "person = circular crop for profile pictures" + width: + type: string + description: Explicit width (e.g., "50px") + height: + type: string + description: Explicit height (e.g., "50px") + horizontalAlignment: + type: string + enum: [left, center, right] + selectAction: + description: Action when image is clicked + oneOf: + - $ref: "#/components/ActionOpenUrl" + - $ref: "#/components/ActionSubmit" + id: + type: string + accessibility: + altTextRequired: true + screenReaderSupport: true + + Media: + name: Media + description: Display audio or video content + category: cardElements + sdkBinding: + type: jsonSchema + elementType: Media + webStandardMapping: + htmlElement: video + semanticType: media + schema: + type: object + required: [type, sources] + properties: + type: + type: string + const: Media + sources: + type: array + items: + type: object + required: [mimeType, url] + properties: + mimeType: + type: string + description: "video/mp4, audio/mp3, etc." + url: + type: string + format: uri + poster: + type: string + format: uri + description: Thumbnail image URL + altText: + type: string + id: + type: string + + RichTextBlock: + name: RichTextBlock + description: Display rich formatted text with inline elements + category: cardElements + sdkBinding: + type: jsonSchema + elementType: RichTextBlock + schema: + type: object + required: [type, inlines] + properties: + type: + type: string + const: RichTextBlock + inlines: + type: array + description: Array of TextRun objects + items: + type: object + properties: + type: + const: TextRun + text: + type: string + color: + type: string + fontType: + type: string + highlight: + type: boolean + isSubtle: + type: boolean + italic: + type: boolean + selectAction: + type: object + size: + type: string + strikethrough: + type: boolean + underline: + type: boolean + weight: + type: string + horizontalAlignment: + type: string + enum: [left, center, right] + id: + type: string + + Table: + name: Table + description: Display tabular data (Adaptive Cards v1.5+) + category: cardElements + sdkBinding: + type: jsonSchema + elementType: Table + webStandardMapping: + htmlElement: table + semanticType: display + schema: + type: object + required: [type, columns, rows] + properties: + type: + type: string + const: Table + columns: + type: array + items: + type: object + properties: + width: + type: string + verticalCellContentAlignment: + type: string + horizontalCellContentAlignment: + type: string + rows: + type: array + items: + type: object + required: [type, cells] + properties: + type: + const: TableRow + cells: + type: array + items: + type: object + properties: + type: + const: TableCell + items: + type: array + showGridLines: + type: boolean + gridStyle: + type: string + enum: [default, emphasis, accent] + id: + type: string + + FactSet: + name: FactSet + description: Display key-value pairs as facts + category: cardElements + sdkBinding: + type: jsonSchema + elementType: FactSet + webStandardMapping: + htmlElement: dl + semanticType: display + schema: + type: object + required: [type, facts] + properties: + type: + type: string + const: FactSet + facts: + type: array + items: + type: object + required: [title, value] + properties: + title: + type: string + description: Fact label + value: + type: string + description: Fact value + id: + type: string + + ImageSet: + name: ImageSet + description: Display a gallery of images + category: cardElements + sdkBinding: + type: jsonSchema + elementType: ImageSet + schema: + type: object + required: [type, images] + properties: + type: + type: string + const: ImageSet + images: + type: array + items: + $ref: "#/components/Image" + imageSize: + type: string + enum: [auto, stretch, small, medium, large] + id: + type: string + + # CONTAINERS + + Container: + name: Container + description: Groups elements together with styling + category: cardContainers + sdkBinding: + type: jsonSchema + elementType: Container + webStandardMapping: + htmlElement: div + ariaRole: region + semanticType: container + schema: + type: object + required: [type, items] + properties: + type: + type: string + const: Container + items: + type: array + description: Array of card elements + style: + type: string + enum: [default, emphasis, good, attention, warning, accent] + verticalContentAlignment: + type: string + enum: [top, center, bottom] + bleed: + type: boolean + description: Bleed to parent container edges + backgroundImage: + type: string + format: uri + minHeight: + type: string + selectAction: + type: object + id: + type: string + + ColumnSet: + name: ColumnSet + description: Arrange elements in columns + category: cardContainers + sdkBinding: + type: jsonSchema + elementType: ColumnSet + webStandardMapping: + htmlElement: div + semanticType: layout + schema: + type: object + required: [type, columns] + properties: + type: + type: string + const: ColumnSet + columns: + type: array + items: + $ref: "#/components/Column" + selectAction: + type: object + style: + type: string + bleed: + type: boolean + minHeight: + type: string + horizontalAlignment: + type: string + id: + type: string + + Column: + name: Column + description: Single column within a ColumnSet + category: cardContainers + sdkBinding: + type: jsonSchema + elementType: Column + schema: + type: object + required: [type, items] + properties: + type: + type: string + const: Column + items: + type: array + description: Elements in this column + width: + description: "auto, stretch, weighted (1, 2, etc.), or pixel (50px)" + oneOf: + - type: string + - type: number + style: + type: string + verticalContentAlignment: + type: string + bleed: + type: boolean + backgroundImage: + type: string + selectAction: + type: object + id: + type: string + + ActionSet: + name: ActionSet + description: Display a set of actions within card body + category: cardContainers + sdkBinding: + type: jsonSchema + elementType: ActionSet + webStandardMapping: + htmlElement: div + ariaRole: group + semanticType: container + schema: + type: object + required: [type, actions] + properties: + type: + type: string + const: ActionSet + actions: + type: array + description: Array of actions + items: + oneOf: + - $ref: "#/components/ActionSubmit" + - $ref: "#/components/ActionOpenUrl" + - $ref: "#/components/ActionShowCard" + - $ref: "#/components/ActionToggleVisibility" + id: + type: string + + # INPUTS + + InputText: + name: Input.Text + description: Single or multi-line text input + category: cardInputs + sdkBinding: + type: jsonSchema + elementType: Input.Text + webStandardMapping: + htmlElement: input + inputType: text + semanticType: input + schema: + type: object + required: [type, id] + properties: + type: + type: string + const: Input.Text + id: + type: string + description: Unique input identifier for form submission + placeholder: + type: string + value: + type: string + description: Default value + isMultiline: + type: boolean + maxLength: + type: integer + style: + type: string + enum: [text, tel, url, email, password] + inlineAction: + description: Action button shown inside input + oneOf: + - $ref: "#/components/ActionSubmit" + - $ref: "#/components/ActionExecute" + isRequired: + type: boolean + errorMessage: + type: string + label: + type: string + description: Accessible label (v1.3+) + accessibility: + labelRequired: true + screenReaderSupport: true + + InputNumber: + name: Input.Number + description: Numeric input with validation + category: cardInputs + sdkBinding: + type: jsonSchema + elementType: Input.Number + webStandardMapping: + htmlElement: input + inputType: number + semanticType: input + schema: + type: object + required: [type, id] + properties: + type: + type: string + const: Input.Number + id: + type: string + placeholder: + type: string + value: + type: number + min: + type: number + max: + type: number + isRequired: + type: boolean + errorMessage: + type: string + label: + type: string + + InputDate: + name: Input.Date + description: Date picker input + category: cardInputs + sdkBinding: + type: jsonSchema + elementType: Input.Date + webStandardMapping: + htmlElement: input + inputType: date + semanticType: input + schema: + type: object + required: [type, id] + properties: + type: + type: string + const: Input.Date + id: + type: string + value: + type: string + format: date + description: ISO 8601 date (YYYY-MM-DD) + placeholder: + type: string + min: + type: string + format: date + max: + type: string + format: date + isRequired: + type: boolean + errorMessage: + type: string + label: + type: string + + InputTime: + name: Input.Time + description: Time picker input + category: cardInputs + sdkBinding: + type: jsonSchema + elementType: Input.Time + webStandardMapping: + htmlElement: input + inputType: time + semanticType: input + schema: + type: object + required: [type, id] + properties: + type: + type: string + const: Input.Time + id: + type: string + value: + type: string + description: "Time in HH:MM format (24-hour)" + placeholder: + type: string + min: + type: string + max: + type: string + isRequired: + type: boolean + errorMessage: + type: string + label: + type: string + + InputToggle: + name: Input.Toggle + description: Checkbox or toggle switch + category: cardInputs + sdkBinding: + type: jsonSchema + elementType: Input.Toggle + webStandardMapping: + htmlElement: input + inputType: checkbox + ariaRole: switch + semanticType: input + schema: + type: object + required: [type, id, title] + properties: + type: + type: string + const: Input.Toggle + id: + type: string + title: + type: string + description: Label text next to toggle + value: + type: string + description: Value when toggled on (default "true") + valueOn: + type: string + default: "true" + valueOff: + type: string + default: "false" + wrap: + type: boolean + isRequired: + type: boolean + errorMessage: + type: string + label: + type: string + + InputChoiceSet: + name: Input.ChoiceSet + description: Drop-down, radio buttons, or checkbox group + category: cardInputs + sdkBinding: + type: jsonSchema + elementType: Input.ChoiceSet + webStandardMapping: + htmlElement: select + ariaRole: listbox + semanticType: input + schema: + type: object + required: [type, id, choices] + properties: + type: + type: string + const: Input.ChoiceSet + id: + type: string + choices: + type: array + items: + type: object + required: [title, value] + properties: + title: + type: string + value: + type: string + style: + type: string + enum: [compact, expanded, filtered] + description: "compact=dropdown, expanded=radio/checkbox, filtered=searchable" + isMultiSelect: + type: boolean + value: + type: string + description: Default selected value(s) + placeholder: + type: string + wrap: + type: boolean + isRequired: + type: boolean + errorMessage: + type: string + label: + type: string + + # ACTIONS + + ActionSubmit: + name: Action.Submit + description: Submit form data to bot or webhook + category: cardActions + sdkBinding: + type: jsonSchema + elementType: Action.Submit + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + schema: + type: object + required: [type, title] + properties: + type: + type: string + const: Action.Submit + title: + type: string + description: Button text + data: + type: object + description: Data merged with input values on submit + iconUrl: + type: string + format: uri + style: + type: string + enum: [default, positive, destructive] + associatedInputs: + type: string + enum: [auto, none] + id: + type: string + accessibility: + keyboardSupport: true + screenReaderSupport: true + + ActionOpenUrl: + name: Action.OpenUrl + description: Open a URL in new tab + category: cardActions + sdkBinding: + type: jsonSchema + elementType: Action.OpenUrl + webStandardMapping: + htmlElement: a + ariaRole: link + semanticType: navigation + schema: + type: object + required: [type, title, url] + properties: + type: + type: string + const: Action.OpenUrl + title: + type: string + url: + type: string + format: uri + iconUrl: + type: string + style: + type: string + id: + type: string + + ActionShowCard: + name: Action.ShowCard + description: Reveal an inline sub-card + category: cardActions + sdkBinding: + type: jsonSchema + elementType: Action.ShowCard + schema: + type: object + required: [type, title, card] + properties: + type: + type: string + const: Action.ShowCard + title: + type: string + card: + type: object + description: Nested Adaptive Card + iconUrl: + type: string + style: + type: string + id: + type: string + + ActionToggleVisibility: + name: Action.ToggleVisibility + description: Show/hide elements dynamically + category: cardActions + sdkBinding: + type: jsonSchema + elementType: Action.ToggleVisibility + schema: + type: object + required: [type, title] + properties: + type: + type: string + const: Action.ToggleVisibility + title: + type: string + targetElements: + type: array + description: IDs of elements to toggle + items: + type: string + id: + type: string + + ActionExecute: + name: Action.Execute + description: Universal Action for bots (v1.4+) + category: cardActions + sdkBinding: + type: jsonSchema + elementType: Action.Execute + schema: + type: object + required: [type, title] + properties: + type: + type: string + const: Action.Execute + title: + type: string + verb: + type: string + description: Action identifier for bot + data: + type: object + iconUrl: + type: string + style: + type: string + associatedInputs: + type: string + enum: [auto, none] + id: + type: string + +extensionPoints: + - id: personal-tab + name: Personal Tab + type: tab + extensionType: iframe + description: | + Personal tab shown in user's personal app scope. Can be pinned + to left rail for quick access. Full web app in iframe with + Teams context via Teams JS SDK. + supportedComponents: + - all (custom HTML/CSS/JS) + constraints: + responsive: true + httpsRequired: true + maxWidth: 1920 + maxHeight: 1080 + context: + provides: + - userId + - userPrincipalName + - tenantId + - locale + - theme + - loginHint + - userObjectId + actions: + - authentication.authenticate + - dialog.open + - pages.getConfig + - app.getContext + extensionTypeConfig: + sdk: teams-js + initialization: + required: true + method: "app.initialize()" + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + communication: + protocol: teams-js + globalObject: microsoftTeams + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/what-are-tabs + + - id: channel-tab + name: Channel/Group Tab + type: tab + extensionType: iframe + description: | + Configurable tab in team channel or group chat. Supports + configuration page for initial setup. Shared across all + team/chat members. + supportedComponents: + - all (custom HTML/CSS/JS) + constraints: + responsive: true + httpsRequired: true + configurationRequired: true + context: + provides: + - channelId + - teamId + - groupId + - channelName + - teamName + - locale + - theme + - entityId + actions: + - pages.config.setConfig + - pages.config.setValidityState + - app.getContext + extensionTypeConfig: + sdk: teams-js + initialization: + required: true + method: "app.initialize()" + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/create-channel-group-tab + + - id: meeting-tab + name: Meeting Tab + type: tab + extensionType: iframe + description: | + Tab shown in Teams meeting (pre-meeting, in-meeting, or + post-meeting). Can access meeting context and participant info. + supportedComponents: + - all (custom HTML/CSS/JS) + constraints: + responsive: true + httpsRequired: true + context: + provides: + - meetingId + - conversationId + - organizerId + - meetingType + - userRole + actions: + - meeting.getMeetingDetails + - meeting.getAppContentStageSharingCapabilities + - meeting.shareAppContentToStage + extensionTypeConfig: + sdk: teams-js + capabilities: + - meeting + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/teams-apps-in-meetings + + - id: bot-chat + name: Bot Conversation + type: bot + extensionType: jsonResponse + description: | + Conversational bot using Bot Framework. Sends and receives + Adaptive Cards for rich interactions. Supports 1:1, group chat, + and channel conversations. + supportedComponents: + - all Adaptive Card elements + - all Adaptive Card inputs + - all Adaptive Card actions + constraints: + maxCardSize: 28000 + schemaVersion: "1.5" + responseTimeout: 15000 + context: + provides: + - conversation + - activity + - turnContext + - userId + - channelId + actions: + - sendActivity + - updateActivity + - deleteActivity + - sendTypingIndicator + extensionTypeConfig: + sdk: botbuilder + protocol: botFramework + schemaFormat: adaptiveCard + schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json + validation: true + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/what-are-bots + + - id: message-extension + name: Message Extension + type: messageExtension + extensionType: jsonResponse + description: | + Search and action commands in compose box and message overflow. + Returns Adaptive Cards or Hero Cards as search results or + action responses. + supportedComponents: + - all Adaptive Card elements (in cards returned) + constraints: + maxResults: 25 + maxCardSize: 28000 + context: + provides: + - commandId + - commandContext + - messagePayload + - queryParameters + actions: + - composeExtension.queryResponse + - task.submitResponse + extensionTypeConfig: + sdk: botbuilder + protocol: botFramework + commandTypes: + - query + - action + schemaFormat: adaptiveCard + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/what-are-messaging-extensions + + - id: meeting-stage + name: Meeting Stage + type: meetingExtension + extensionType: iframe + description: | + Full-screen app experience shared to meeting stage. All + participants see the same view. Supports collaborative + scenarios like whiteboards, design reviews, etc. + supportedComponents: + - all (custom HTML/CSS/JS) + constraints: + responsive: true + httpsRequired: true + collaborative: true + context: + provides: + - meetingId + - frameContext: meetingStage + - shareToStage + actions: + - meeting.getAppContentStageSharingCapabilities + - meeting.getAppContentStageSharingState + extensionTypeConfig: + sdk: teams-js + capabilities: + - meeting + initialization: + method: "app.initialize()" + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/enable-and-configure-your-app-for-teams-meetings + + - id: meeting-panel + name: Meeting Side Panel + type: meetingExtension + extensionType: iframe + description: | + Side panel shown during meeting. Personal view per participant. + Used for notes, polls, Q&A, resources, etc. + supportedComponents: + - all (custom HTML/CSS/JS) + constraints: + responsive: true + httpsRequired: true + maxWidth: 400 + context: + provides: + - meetingId + - frameContext: sidePanel + - participantId + actions: + - meeting.getMeetingDetails + - meeting.getParticipant + extensionTypeConfig: + sdk: teams-js + capabilities: + - meeting + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/apps-in-teams-meetings/build-apps-for-teams-meeting-stage + + - id: adaptive-card-message + name: Adaptive Card in Message + type: message + extensionType: jsonResponse + description: | + Standalone Adaptive Card posted to chat/channel by bot or + via webhook. Supports rich interactive content. + supportedComponents: + - all Adaptive Card elements + - all Adaptive Card inputs + - all Adaptive Card actions + constraints: + maxCardSize: 28000 + schemaVersion: "1.5" + actionTypes: + - Action.Submit + - Action.OpenUrl + - Action.Execute + - Action.ToggleVisibility + context: + provides: + - cardId + - conversationId + actions: + - refreshCard + - updateCard + extensionTypeConfig: + schemaFormat: adaptiveCard + schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json + validation: true + rendering: native + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference + + - id: task-module + name: Task Module (Dialog) + type: dialog + extensionType: iframe + description: | + Modal dialog for focused tasks. Can show iframe or Adaptive + Card. Opened via Teams JS SDK or bot card action. + supportedComponents: + - all (iframe mode) + - all Adaptive Card elements (card mode) + constraints: + maxWidth: 600 + maxHeight: 600 + responsive: true + context: + provides: + - taskInfo + - completionBotId + actions: + - dialog.submit + - dialog.url.submit + extensionTypeConfig: + modes: + - iframe + - adaptiveCard + sdk: teams-js + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/what-are-task-modules + +policies: + componentRequirement: + level: required + scope: bots + rationale: | + Teams bots MUST use Adaptive Cards for rich interactive messages. + Plain text is supported but Adaptive Cards are required for UI. + Tabs are iframe-based and have no component requirement. + + customComponents: + allowed: true + scope: tabs + constraints: + - httpsRequired + - sandboxOnly + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/create-personal-tab + rationale: | + Tabs are full web applications with complete freedom to use any + HTML/CSS/JS framework. Bots must use Adaptive Cards exclusively. + + publishing: + sideloading: + name: Sideloading + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: false + notes: | + Development/testing mode. Apps can be uploaded directly to + Teams tenant without review. + + organizationStore: + name: Organization App Catalog + componentRequirement: required + customComponentsAllowed: true + reviewRequired: true + adminApprovalRequired: true + notes: | + Internal apps distributed within organization. IT admin + reviews and approves before catalog listing. + + teamsStore: + name: Microsoft Teams Store + componentRequirement: required + customComponentsAllowed: true + reviewRequired: true + certificationRequired: true + securityReviewRequired: true + notes: | + Public app store distribution. Requires passing app validation, + security review, and compliance certification. + validationUrl: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines + + designGuidelines: + required: true + designSystem: Fluent UI + designSystemUrl: https://developer.microsoft.com/en-us/fluentui + adaptiveCardsDesigner: https://adaptivecards.io/designer/ + guidelines: + - Use Adaptive Cards Designer for card development + - Follow Fluent UI design principles for tabs + - Support light and dark themes + - Ensure mobile responsiveness + - Provide clear error messages + - Use appropriate card schema version + guidelinesUrl: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/design/design-teams-app-overview + + security: + httpsRequired: true + authenticationRequired: false + ssoSupported: true + description: | + All tab URLs must use HTTPS. Teams supports SSO via Azure AD. + Bots use Bot Framework authentication. Apps can request + resource-specific consent (RSC) permissions. + rscPermissions: + - TeamSettings.Read.Group + - ChannelMessage.Read.Group + - TeamsActivity.Send + - ChatMessage.Read.Chat + - OnlineMeeting.ReadBasic.Chat + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/authentication/authentication + +renderingEngines: + adaptive-cards-native: + type: native + name: Adaptive Cards Native Renderer + description: | + Teams natively renders Adaptive Cards sent by bots, message + extensions, and webhooks. Cards are defined as JSON and rendered + consistently across Teams desktop, mobile, and web. + schemaSupport: + dataSchema: adaptiveCard + schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json + version: "1.5" + customRenderers: false + platforms: + - Teams Desktop (Windows, macOS, Linux) + - Teams Mobile (iOS, Android) + - Teams Web + - Outlook Desktop + - Outlook Web + - Microsoft 365 App + + teams-tab-iframe: + type: custom + name: Teams Tab Iframe Renderer + description: | + Tabs are rendered as web pages in sandboxed iframes. Developers + have full control over HTML/CSS/JS. Teams JS SDK provides bridge + to Teams context and capabilities. + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + cspPolicy: "Must allow https://teams.microsoft.com as frame-ancestor" + platforms: + - Teams Desktop (Windows, macOS, Linux) + - Teams Mobile (iOS, Android) + - Teams Web + +jsonFormsIntegration: + supported: true + scope: tabs + notes: | + Tabs can use JSON Forms or any other form library since they're + full web apps. Adaptive Cards have their own input system. + +mcpAppsIntegration: + supported: false + notes: | + Not currently integrated with MCP Apps specification. + +extensionType: hybrid + +extensions: + declarativeSchemas: + enabled: true + scope: adaptiveCards + schemaFormat: json + description: | + Adaptive Cards are entirely JSON-based declarative UI. Bots + construct cards as JSON conforming to Adaptive Card schema. + validation: + designerTool: https://adaptivecards.io/designer/ + sdkValidation: true + runtimeValidation: true + schemaUrl: http://adaptivecards.io/schemas/adaptive-card.json + schemaVersions: + - "1.0" + - "1.2" + - "1.3" + - "1.4" + - "1.5" + fallbackSupport: true + documentation: https://adaptivecards.io/ + + i18n: + enabled: true + localeDetection: automatic + description: | + Teams provides user locale via Teams JS SDK context. Apps can + localize tab content, bot messages, and Adaptive Card text. + implementation: + clientProvides: + - locale + - userLocale + - osLocale + developerResponsibility: + - Localize tab UI + - Localize Adaptive Card text + - Localize bot messages + - Handle RTL languages + - Format dates/times/numbers per locale + supportedLocales: + - en-US + - en-GB + - es-ES + - es-MX + - fr-FR + - fr-CA + - de-DE + - it-IT + - ja-JP + - ko-KR + - pt-BR + - ru-RU + - zh-CN + - zh-TW + - ar-SA + - cs-CZ + - da-DK + - nl-NL + - fi-FI + - he-IL + - hi-IN + - hu-HU + - id-ID + - nb-NO + - pl-PL + - pt-PT + - ro-RO + - sv-SE + - th-TH + - tr-TR + - uk-UA + - vi-VN + appManifest: + localizationInfoRequired: true + additionalLanguagesField: true + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/apps-localization + + compliance: + enabled: true + description: | + Apps distributed via Teams Store must pass Microsoft's app + validation, security review, and compliance certification. + requirements: + appValidation: + required: true + scope: teamsStore + includes: + - Manifest validation + - Functionality testing + - Performance testing + - UI/UX review + - Content policy compliance + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines + + securityReview: + required: true + scope: teamsStore + includes: + - Data handling and privacy + - Authentication security + - API usage patterns + - Permission scope audit + - Vulnerability assessment + + publisherVerification: + required: true + scope: teamsStore + description: | + Publisher must verify identity via Microsoft Partner Center. + Shows blue verified badge in app listing. + + publisherAttestation: + required: true + scope: teamsStore + description: | + Publisher attests to security, privacy, and compliance practices. + + certifications: + microsoft365Certification: + available: true + tier: certified + description: | + Apps can achieve Microsoft 365 Certified status by passing + comprehensive security, compliance, and privacy assessments. + url: https://learn.microsoft.com/en-us/microsoft-365-app-certification/overview + + cloudSecurityAlliance: + available: true + description: CSA STAR attestation available + + iso27001: + available: true + description: ISO 27001 certification for data security + + soc2: + available: true + description: SOC 2 Type II attestation + + dataResidency: + supported: true + description: | + Teams supports data residency commitments for enterprise + customers via Microsoft 365 data location settings. + + documentation: https://learn.microsoft.com/en-us/microsoft-365-app-certification/docs/enterprise-app-certification-guide + + manifest: + file: manifest.json + description: | + Every Teams app requires a manifest.json file defining app + metadata, capabilities, permissions, and resource URLs. + schema: https://developer.microsoft.com/json-schemas/teams/v1.24/MicrosoftTeams.schema.json + currentVersion: "1.24" + packageFormat: .zip + packageContents: + - manifest.json + - color.png (192x192) + - outline.png (32x32) + keyProperties: + - id: Unique app ID (GUID) + - version: App version + - packageName: Reverse domain notation + - developer: Publisher info + - name: App name (short, full) + - description: App description (short, full) + - icons: App icons + - accentColor: Brand color (hex) + - configurableTabs: Channel/group tabs + - staticTabs: Personal tabs + - bots: Bot configuration + - composeExtensions: Message extensions + - permissions: Requested permissions + - validDomains: Allowed domains + - webApplicationInfo: SSO configuration + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema + + analytics: + enabled: true + description: | + Teams provides app analytics in Partner Center showing usage, + installations, active users, and engagement metrics. + metrics: + - Daily/Monthly Active Users (DAU/MAU) + - Installations and uninstalls + - User retention + - Feature usage + - Platform distribution (desktop/mobile/web) + - Geographic distribution + - Tenant size distribution + dashboard: https://partner.microsoft.com/dashboard/ + customTelemetry: + supported: true + description: Apps can implement custom telemetry using Application Insights + + testing: + enabled: true + description: Tools and methods for testing Teams apps + tools: + adaptiveCardsDesigner: + url: https://adaptivecards.io/designer/ + description: Visual designer for Adaptive Cards with live preview + features: + - Visual card composition + - JSON export/import + - Sample data binding + - Host config preview + - Validation errors + + teamsAppStudio: + deprecated: true + replacement: Teams Developer Portal + description: Legacy tool replaced by Developer Portal + + developerPortal: + url: https://dev.teams.microsoft.com/ + description: Web-based app management and testing platform + features: + - App manifest editor + - Validation tools + - Test in Teams + - App submission + - Analytics + + teamsToolkit: + url: https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teams-toolkit-fundamentals + description: VS Code extension for Teams app development + features: + - Project scaffolding + - Local debugging + - Azure provisioning + - CI/CD integration + - Sample apps + + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/test-app-overview + + accessibilityFeatures: + keyboardNavigation: true + screenReaderSupport: true + highContrastMode: true + description: | + Teams platform provides built-in accessibility for Adaptive Cards. + Tab apps must implement their own accessibility features. + adaptiveCardsAccessibility: + - Automatic screen reader support + - Keyboard navigation built-in + - High contrast theme support + - Focus management + - ARIA attributes generated + tabAccessibility: + - Developer must implement WCAG 2.1 AA compliance + - Use semantic HTML + - Provide ARIA labels + - Ensure keyboard navigation + - Support high contrast themes + - Test with screen readers + guidelines: + - Use label property on Adaptive Card inputs (v1.3+) + - Provide alt text for images + - Ensure sufficient color contrast + - Support keyboard-only navigation + - Provide skip links in tabs + - Test with Narrator, JAWS, NVDA + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/design/design-teams-app-accessibility + + rateLimits: + description: Rate limits for Teams platform APIs + limits: + botMessages: + rate: "1 message per second per conversation" + burst: "Up to 10 messages burst" + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit + + graphApi: + rate: "Varies by endpoint and tenant" + description: Microsoft Graph API has per-app and per-tenant limits + documentation: https://learn.microsoft.com/en-us/graph/throttling + + adaptiveCardRefresh: + rate: "1 refresh per 60 seconds per user per card" + + messageExtensionQueries: + rate: "5 queries per second per user" + + retryPolicy: "Use exponential backoff with jitter" + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/rate-limit + + securityFeatures: + authentication: + aadSsoSupported: true + oauthSupported: true + description: | + Teams supports SSO via Azure AD. Tabs can use Teams JS SDK + authentication namespace. Bots use Bot Framework auth. + + permissions: + rscPermissions: true + description: | + Resource-specific consent allows apps to request granular + permissions for team/chat resources without admin consent. + + contentSecurityPolicy: + required: true + frameAncestors: "Must allow https://teams.microsoft.com" + + features: + - Azure AD SSO + - OAuth 2.0 support + - Resource-specific consent (RSC) + - Bot authentication via Bot Framework + - Token exchange for seamless auth + - Secure iframe sandboxing + - HTTPS requirement for all endpoints + + documentation: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/authentication/authentication + +notes: | + Microsoft Teams represents a hybrid extensibility platform combining: + + 1. **Adaptive Cards** (Declarative JSON): + - Used by bots and message extensions + - JSON-based declarative UI (similar to Slack Block Kit) + - Native rendering across Teams, Outlook, Microsoft 365 + - Schema version 1.5 with rich elements and actions + - Required for bot messages with UI + + 2. **Tabs** (Iframe-based): + - Full web applications in sandboxed iframes + - Complete freedom with HTML/CSS/JS frameworks + - Teams JS SDK provides context and capabilities + - Personal, channel/group, and meeting scopes + - Can extend to Outlook and Microsoft 365 app + + 3. **Bots** (Conversational + Cards): + - Built on Microsoft Bot Framework + - Send/receive Adaptive Cards for rich interactions + - Support 1:1, group chat, channel conversations + - Can be proactive or reactive + + 4. **Message Extensions**: + - Search and action commands + - Extend compose box and message overflow menu + - Return Adaptive Cards as results + - Built on Bot Framework protocol + + 5. **Meeting Extensions**: + - In-meeting apps, stages, and side panels + - Meeting stage for collaborative experiences + - Side panels for personal tools + - Pre-meeting and post-meeting tabs + + Key platform characteristics: + - Hybrid model: Declarative (Adaptive Cards) + Custom (Tabs) + - Cross-Microsoft 365: Works in Teams, Outlook, M365 app + - Modern SDK: TeamsJS v2+ with tree-shaking support + - Enterprise-ready: Comprehensive compliance and security + - Global reach: 40+ supported locales + - Accessibility: Built-in for cards, developer-implemented for tabs + + Development tools: + - Adaptive Cards Designer for visual card building + - Teams Developer Portal for app management + - Teams Toolkit for VS Code + - Comprehensive documentation and samples + +metadata: + fenestra: + createdAt: "2025-12-30" + author: "Fenestra Specification Team" + category: "Collaboration Platform" + tags: + - collaboration + - microsoft-365 + - adaptive-cards + - iframe + - bots + - meetings + - hybrid + relatedPlatforms: + - Slack (similar declarative UI with Block Kit) + - Discord (bots and embeds) + - Zoom Apps (meeting extensions) + references: + - https://learn.microsoft.com/en-us/microsoftteams/platform/ + - https://adaptivecards.io/ + - https://learn.microsoft.com/en-us/javascript/api/overview/msteams-client + - https://dev.botframework.com/ diff --git a/specs/fenestra/examples/0.1.0/vscode.fenestra.yaml b/specs/fenestra/examples/0.1.0/vscode.fenestra.yaml new file mode 100644 index 0000000..de7ea7f --- /dev/null +++ b/specs/fenestra/examples/0.1.0/vscode.fenestra.yaml @@ -0,0 +1,1184 @@ +# Fenestra Document: Visual Studio Code Extension Platform +# +# VS Code represents a dual-execution model with Extension Host + Webview architecture. +# Extensions run in a Node.js Extension Host process with access to the vscode API, +# while custom UI can be rendered in sandboxed Webview iframes. + +fenestra: "0.1.0" + +info: + title: Visual Studio Code Extension Platform + version: "1.0.0" + description: | + Visual Studio Code's Extension API enables developers to extend the editor + with new functionality through a dual-architecture model. + + Key characteristics: + - Extension Host process (Node.js) for extension logic and VS Code API access + - Webview panels (sandboxed iframes) for custom HTML/CSS/JS UI + - Communication via postMessage between Extension Host and Webviews + - Webview UI Toolkit for consistent, accessible UI components + - Multiple contribution points (commands, views, editors, etc.) + - Rich extension capabilities: language support, debugging, source control, and more + + contact: + name: VS Code Team + url: https://code.visualstudio.com/api + email: vscode@microsoft.com + +platform: + name: Visual Studio Code + vendor: Microsoft Corporation + documentation: https://code.visualstudio.com/api + appMarketplace: https://marketplace.visualstudio.com/vscode + +sdks: + vscode-api: + name: VS Code Extension API + packageManager: npm + package: "vscode" + typesPackage: "@types/vscode" + version: "^1.85.0" + documentation: https://code.visualstudio.com/api/references/vscode-api + description: | + The core VS Code Extension API. Extensions import this module to access + all VS Code capabilities including commands, windows, editors, workspace, + languages, debugging, and more. + + Note: The 'vscode' module is provided by the Extension Host runtime and + should be declared as a dependency but not bundled. + exports: + commands: + type: utility + description: Execute and register commands (namespace) + window: + type: utility + description: Window management, UI elements, messages, input boxes (namespace) + workspace: + type: utility + description: Workspace folders, file system, configuration (namespace) + languages: + type: utility + description: Language features, diagnostics, hover, completion (namespace) + debug: + type: utility + description: Debugging sessions and configurations (namespace) + scm: + type: utility + description: Source control management (namespace) + extensions: + type: utility + description: Access to other extensions (namespace) + TreeView: + type: type + description: Tree view in sidebar or panel (class) + TreeDataProvider: + type: type + description: Data provider for tree views (interface) + WebviewPanel: + type: type + description: Webview panel with custom HTML content (interface) + CustomTextEditorProvider: + type: type + description: Custom editor for text files (interface) + CustomReadonlyEditorProvider: + type: type + description: Custom read-only editor provider (interface) + StatusBarItem: + type: type + description: Status bar item (class) + QuickPick: + type: type + description: Quick pick UI for user selection (interface) + InputBox: + type: type + description: Input box for user text entry (interface) + Uri: + type: type + description: Universal resource identifier (class) + Range: + type: type + description: Text range with start and end positions (class) + Position: + type: type + description: Position in a text document (class) + TextDocument: + type: type + description: Text document representation (interface) + + webview-ui-toolkit: + name: Webview UI Toolkit + packageManager: npm + package: "@vscode/webview-ui-toolkit" + version: "^1.4.0" + repository: https://github.com/microsoft/vscode-webview-ui-toolkit + documentation: https://github.com/microsoft/vscode-webview-ui-toolkit/blob/main/docs/getting-started.md + description: | + A component library for building webview-based extensions. Provides + Web Components that match VS Code's look and feel with built-in theming + support (light, dark, high contrast). + + Uses FAST Foundation under the hood for accessible, performant components. + exports: + provideVSCodeDesignSystem: + type: utility + description: Initialize the design system for webview (function) + vsCodeButton: + type: component + description: Button component + vsCodeCheckbox: + type: component + description: Checkbox component + vsCodeDataGrid: + type: component + description: Data grid/table component + vsCodeDropdown: + type: component + description: Dropdown/select component + vsCodeLink: + type: component + description: Hyperlink component + vsCodeOption: + type: component + description: Option for dropdowns + vsCodePanels: + type: component + description: Tab panels container + vsCodeProgressRing: + type: component + description: Loading spinner + vsCodeRadio: + type: component + description: Radio button + vsCodeRadioGroup: + type: component + description: Radio button group + vsCodeTextArea: + type: component + description: Multi-line text input + vsCodeTextField: + type: component + description: Single-line text input + vsCodeDivider: + type: component + description: Visual divider + vsCodeBadge: + type: component + description: Badge/pill component + vsCodeTag: + type: component + description: Tag component + + yeoman-generator: + name: Yeoman VS Code Extension Generator + packageManager: npm + package: "generator-code" + version: "^1.8.0" + repository: https://github.com/microsoft/vscode-generator-code + documentation: https://code.visualstudio.com/api/get-started/your-first-extension + description: | + Yeoman generator for scaffolding new VS Code extensions. + Supports TypeScript, JavaScript, and various extension types. + starterTemplate: + command: "npm install -g yo generator-code && yo code" + documentation: https://code.visualstudio.com/api/get-started/your-first-extension + + vsce: + name: Visual Studio Code Extensions CLI + packageManager: npm + package: "@vscode/vsce" + version: "^2.22.0" + repository: https://github.com/microsoft/vscode-vsce + documentation: https://code.visualstudio.com/api/working-with-extensions/publishing-extension + description: | + Command-line tool for packaging, publishing, and managing VS Code extensions. + cliTool: + package: "@vscode/vsce" + globalInstall: true + commands: + package: "Package extension into .vsix file" + publish: "Publish extension to marketplace" + ls: "List packaged files" + +componentCatalog: + categories: + action: + name: Actions + description: Interactive button and action components + components: [button, link] + + input: + name: Inputs + description: Form input controls + components: [textField, textArea, dropdown, checkbox, radio, radioGroup] + + data: + name: Data Display + description: Components for displaying data + components: [dataGrid, badge, tag, progressRing] + + layout: + name: Layout + description: Layout and container components + components: [panels, divider] + + treeView: + name: Tree Views + description: Hierarchical tree view components + components: [treeView, treeItem] + + editor: + name: Editor Components + description: Editor-related UI components + components: [statusBarItem, quickPick, inputBox] + + components: + button: + name: Button + description: VS Code styled button for webviews + category: action + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeButton + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + appearance: + type: string + enum: [primary, secondary, icon] + description: Button visual style + disabled: + type: boolean + description: Whether button is disabled + autofocus: + type: boolean + description: Auto-focus on load + variants: + - primary + - secondary + - icon + examples: + - title: Primary Button + code: | + Click Me + language: html + - title: Icon Button + code: | + + + + language: html + accessibility: + keyboardSupport: true + screenReaderSupport: true + ariaSupport: true + + textField: + name: Text Field + description: Single-line text input + category: input + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeTextField + webStandardMapping: + htmlElement: input + inputType: text + ariaRole: textbox + semanticType: input + props: + value: + type: string + description: Input value + placeholder: + type: string + description: Placeholder text + disabled: + type: boolean + readonly: + type: boolean + maxlength: + type: number + examples: + - title: Basic Text Field + code: | + + language: html + accessibility: + keyboardSupport: true + screenReaderSupport: true + labelRequired: true + + textArea: + name: Text Area + description: Multi-line text input + category: input + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeTextArea + webStandardMapping: + htmlElement: textarea + ariaRole: textbox + semanticType: input + props: + value: + type: string + placeholder: + type: string + rows: + type: number + cols: + type: number + resize: + type: string + enum: [none, both, horizontal, vertical] + examples: + - title: Text Area + code: | + + + language: html + + dropdown: + name: Dropdown + description: Dropdown select menu + category: input + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeDropdown + webStandardMapping: + htmlElement: select + ariaRole: listbox + semanticType: input + props: + disabled: + type: boolean + position: + type: string + enum: [above, below] + examples: + - title: Dropdown + code: | + + Option 1 + Option 2 + Option 3 + + language: html + + checkbox: + name: Checkbox + description: Checkbox input + category: input + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeCheckbox + webStandardMapping: + htmlElement: input[type="checkbox"] + ariaRole: checkbox + semanticType: input + props: + checked: + type: boolean + disabled: + type: boolean + examples: + - title: Checkbox + code: | + Enable feature + language: html + + radio: + name: Radio Button + description: Single radio button + category: input + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeRadio + webStandardMapping: + htmlElement: input[type="radio"] + ariaRole: radio + semanticType: input + examples: + - title: Radio Button + code: | + Choice 1 + language: html + + radioGroup: + name: Radio Group + description: Group of radio buttons + category: input + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeRadioGroup + webStandardMapping: + ariaRole: radiogroup + semanticType: input + examples: + - title: Radio Group + code: | + + + Option 1 + Option 2 + Option 3 + + language: html + + dataGrid: + name: Data Grid + description: Table/grid for displaying data + category: data + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeDataGrid + webStandardMapping: + htmlElement: table + ariaRole: grid + semanticType: display + props: + gridTemplateColumns: + type: string + description: CSS grid template columns + generateHeader: + type: string + enum: [default, none, sticky] + examples: + - title: Data Grid + code: | + + + Name + Value + + + Item 1 + 100 + + + language: html + + panels: + name: Panels + description: Tab panels for organizing content + category: layout + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodePanels + webStandardMapping: + ariaRole: tablist + semanticType: navigation + examples: + - title: Tab Panels + code: | + + Tab 1 + Tab 2 + Content 1 + Content 2 + + language: html + + badge: + name: Badge + description: Badge/pill component for counts or status + category: data + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeBadge + webStandardMapping: + htmlElement: span + semanticType: display + examples: + - title: Badge + code: | + 5 + language: html + + divider: + name: Divider + description: Visual separator + category: layout + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeDivider + webStandardMapping: + htmlElement: hr + ariaRole: separator + semanticType: layout + examples: + - title: Divider + code: | + + language: html + + progressRing: + name: Progress Ring + description: Loading/progress indicator + category: data + sdkBinding: + sdk: webview-ui-toolkit + export: vsCodeProgressRing + webStandardMapping: + ariaRole: progressbar + semanticType: display + examples: + - title: Progress Ring + code: | + + language: html + + treeView: + name: Tree View + description: Hierarchical tree view in sidebar or panel + category: treeView + sdkBinding: + sdk: vscode-api + export: TreeView + examples: + - title: Tree View Registration + code: | + const treeDataProvider = new MyTreeDataProvider(); + const treeView = vscode.window.createTreeView('myView', { + treeDataProvider + }); + language: typescript + + statusBarItem: + name: Status Bar Item + description: Item in the status bar + category: editor + sdkBinding: + sdk: vscode-api + export: StatusBarItem + examples: + - title: Status Bar Item + code: | + const statusBarItem = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right, + 100 + ); + statusBarItem.text = "$(check) Ready"; + statusBarItem.show(); + language: typescript + + quickPick: + name: Quick Pick + description: Quick pick UI for user selection + category: editor + sdkBinding: + sdk: vscode-api + export: QuickPick + examples: + - title: Quick Pick + code: | + const quickPick = vscode.window.createQuickPick(); + quickPick.items = [ + { label: 'Option 1' }, + { label: 'Option 2' } + ]; + quickPick.onDidChangeSelection(selection => { + console.log(selection[0].label); + }); + quickPick.show(); + language: typescript + +policies: + componentRequirement: + level: recommended + scope: all + rationale: | + VS Code API is REQUIRED for extension functionality, but UI components + are RECOMMENDED, not required. The Webview UI Toolkit is recommended + for webviews to ensure consistent look and feel, but developers can + use custom HTML/CSS or other frameworks. + + customComponents: + allowed: true + constraints: + - sandboxOnly + registrationRequired: false + approvalRequired: false + documentation: https://code.visualstudio.com/api/extension-guides/webview + rationale: | + Extensions can use custom UI in webviews. The Extension Host runs + extension code in a Node.js process with VS Code API access, while + webviews run custom HTML/CSS/JS in sandboxed iframes. + + publishing: + privateExtensions: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: false + notes: | + Private extensions (.vsix files) can be installed locally or + distributed privately without marketplace review. + + publicExtensions: + componentRequirement: optional + customComponentsAllowed: true + reviewRequired: true + notes: | + Public marketplace extensions undergo automated and manual review + for security, quality, and adherence to guidelines. + + verifiedPublisher: + certificationRequired: true + notes: | + Verified publisher status requires domain verification and + adherence to publisher agreement. + + designGuidelines: + required: false + designSystem: "Webview UI Toolkit" + designSystemUrl: https://github.com/microsoft/vscode-webview-ui-toolkit + designTokensProvided: true + guidelines: + - Use Webview UI Toolkit for consistent theming + - Support light, dark, and high contrast themes + - Follow VS Code UX guidelines for extensions + - Use Codicons for icons + - Ensure keyboard accessibility + + security: + sandbox: true + sandboxDescription: | + Webviews run in sandboxed iframes with limited permissions. + Extension Host code runs in a separate Node.js process. + Communication between Extension Host and Webview uses postMessage. + cspPolicy: "default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}' ${webview.cspSource}; img-src ${webview.cspSource} https: data:;" + securityGuidelines: https://code.visualstudio.com/api/extension-guides/webview#security + +extensionPoints: + - id: sidebar-webview + name: Sidebar Webview Panel + type: sidebar + extensionType: iframe + description: | + Custom webview panel in the sidebar. Extensions register a view + in the activity bar and provide webview content. + supportedComponents: + - all webview components + constraints: + resizable: true + responsive: true + context: + provides: + - workspace + - activeEditor + - selection + - theme + actions: + - postMessage + - receiveMessage + - setState + - getState + extensionTypeConfig: + sandboxAttributes: + - allow-scripts + - allow-forms + communication: + globalObject: "acquireVsCodeApi" + initialization: + method: "acquireVsCodeApi() in webview" + async: false + asyncPattern: promises + capabilities: + context: true + uiActions: true + dataActions: true + events: true + examples: + - title: Webview Panel Registration + code: | + const provider = { + resolveWebviewView(webviewView) { + webviewView.webview.options = { + enableScripts: true + }; + webviewView.webview.html = getWebviewContent(); + } + }; + vscode.window.registerWebviewViewProvider('myView', provider); + language: typescript + + - id: editor-webview + name: Editor Webview Panel + type: panel + extensionType: iframe + description: | + Standalone webview panel that opens in the editor area. + Can be used for custom editors, dashboards, or tools. + supportedComponents: + - all webview components + constraints: + resizable: true + responsive: true + multiple: true + context: + provides: + - workspace + - theme + actions: + - postMessage + - receiveMessage + - setState + - getState + extensionTypeConfig: + sandboxAttributes: + - allow-scripts + - allow-forms + communication: + globalObject: "acquireVsCodeApi" + examples: + - title: Create Webview Panel + code: | + const panel = vscode.window.createWebviewPanel( + 'myPanel', + 'My Panel', + vscode.ViewColumn.One, + { + enableScripts: true + } + ); + panel.webview.html = getWebviewContent(); + language: typescript + + - id: custom-editor + name: Custom Editor + type: panel + extensionType: codedComponents + description: | + Custom editor for specific file types. Can be text-based or + fully custom webview-based editor. + supportedComponents: + - all webview components (for webview editors) + constraints: + fileTypes: true + multiple: true + context: + provides: + - document + - workspace + - theme + actions: + - edit + - save + - undo + - redo + extensionTypeConfig: + sdk: vscode-api + runtime: + type: directExecution + bundling: developerBuild + examples: + - title: Custom Text Editor + code: | + class MyEditorProvider implements vscode.CustomTextEditorProvider { + resolveCustomTextEditor(document, webviewPanel) { + webviewPanel.webview.options = { + enableScripts: true + }; + webviewPanel.webview.html = getEditorHtml(); + } + } + vscode.window.registerCustomEditorProvider( + 'myEditor.edit', + new MyEditorProvider() + ); + language: typescript + + - id: tree-view + name: Tree View + type: sidebar + extensionType: codedComponents + description: | + Hierarchical tree view in sidebar or panel. Uses TreeDataProvider + to supply data, VS Code renders the tree natively. + supportedComponents: + - treeView + - treeItem + constraints: + resizable: true + collapsible: true + context: + provides: + - selection + - workspace + actions: + - reveal + - refresh + extensionTypeConfig: + sdk: vscode-api + runtime: + type: directExecution + bundling: developerBuild + examples: + - title: Tree View + code: | + class MyTreeDataProvider implements vscode.TreeDataProvider { + getTreeItem(element) { + return element; + } + getChildren(element) { + return this.getChildElements(element); + } + } + vscode.window.createTreeView('myView', { + treeDataProvider: new MyTreeDataProvider() + }); + language: typescript + + - id: status-bar + name: Status Bar + type: toolbar + extensionType: codedComponents + description: | + Items in the status bar at the bottom of the window. + Can show text, icons, and be clickable. + supportedComponents: + - statusBarItem + constraints: + alignment: true + priority: true + context: + provides: + - workspace + - activeEditor + actions: + - show + - hide + - dispose + extensionTypeConfig: + sdk: vscode-api + examples: + - title: Status Bar Item + code: | + const item = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right, + 100 + ); + item.text = "$(rocket) Extension"; + item.command = 'extension.command'; + item.show(); + language: typescript + + - id: activity-bar + name: Activity Bar + type: toolbar + extensionType: codedComponents + description: | + Icon in the activity bar (left side) that opens a view container + in the sidebar. Defined via package.json contribution points. + supportedComponents: [] + constraints: + iconRequired: true + context: + provides: + - viewContainer + extensionTypeConfig: + sdk: vscode-api + + - id: quick-pick + name: Quick Pick + type: modal + extensionType: codedComponents + description: | + Quick pick UI for user selection. Native VS Code component + rendered by the editor, controlled via Extension API. + supportedComponents: + - quickPick + constraints: + searchable: true + multiSelect: true + context: + provides: + - workspace + actions: + - show + - hide + - dispose + extensionTypeConfig: + sdk: vscode-api + + - id: input-box + name: Input Box + type: modal + extensionType: codedComponents + description: | + Input box for text entry. Native VS Code component. + supportedComponents: + - inputBox + constraints: + validation: true + context: + provides: + - workspace + extensionTypeConfig: + sdk: vscode-api + +renderingEngines: + webview-iframe: + type: custom + name: Webview (HTML + CSS + JS in Iframe) + description: | + Webviews run custom HTML/CSS/JavaScript in sandboxed iframes. + Developers can use Webview UI Toolkit, React, Vue, or any framework. + Communication with Extension Host via postMessage. + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + cspPolicy: "default-src 'none'; style-src ${webview.cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}'" + platforms: + - VS Code Desktop (Windows, macOS, Linux) + - VS Code Web (browser) + + native-vscode: + type: custom + name: Native VS Code Components + description: | + Tree views, status bar items, quick picks, and other native UI + elements are rendered by VS Code itself. Extensions provide data + and behavior via the Extension API. + platforms: + - VS Code Desktop (Windows, macOS, Linux) + - VS Code Web (browser) + +architecture: + executionModel: dual-process + description: | + VS Code extensions use a dual-process architecture: + + 1. Extension Host (Node.js): Runs extension code with access to VS Code API + - Full VS Code API access (vscode.*) + - File system access, Node.js capabilities + - Can open webviews and create UI elements + - No direct DOM access to editor + + 2. Webview (Sandboxed Iframe): Custom HTML/CSS/JS for rich UI + - Full DOM access for custom rendering + - No direct VS Code API access + - Communicates with Extension Host via postMessage + - Uses acquireVsCodeApi() for message passing + + This separation ensures security while allowing rich custom UIs. + + communication: + protocol: postMessage + description: | + Extension Host and Webview communicate via window.postMessage API. + + Extension Host -> Webview: webview.postMessage(data) + Webview -> Extension Host: vscode.postMessage(data) + + Extension Host listens: webview.onDidReceiveMessage(msg => { ... }) + Webview listens: window.addEventListener('message', event => { ... }) + + Webview gets API handle: const vscode = acquireVsCodeApi() + +extensionType: codedComponents + +jsonFormsIntegration: + supported: true + rendererSet: custom + customRenderersAllowed: true + notes: | + Developers can integrate JSON Forms in webviews with custom renderers + using Webview UI Toolkit or other frameworks. + +mcpAppsIntegration: + supported: false + notes: | + Not currently integrated with MCP Apps specification, but webview + architecture could potentially support MCP Apps UI resources. + +extensions: + compliance: + marketplaceReview: + required: true + scope: publicExtensions + description: | + All public marketplace extensions undergo review: + 1. Automated security scanning + 2. Malware detection + 3. Code analysis for suspicious patterns + 4. Manual review for quality and functionality + 5. Verification of description accuracy + timeline: "Typically 1-3 business days" + documentation: https://code.visualstudio.com/api/working-with-extensions/publishing-extension#review-extension-submission + + securityRequirements: + - name: Content Security Policy + description: Webviews must use restrictive CSP + required: true + - name: Sandboxing + description: Webviews run in sandboxed iframes + required: true + - name: API Access + description: Only access VS Code API from Extension Host + required: true + - name: Data Privacy + description: No unauthorized telemetry or data collection + required: true + - name: Sensitive Data + description: Secure handling of credentials and tokens + required: true + + securityGuidelines: + url: https://code.visualstudio.com/api/extension-guides/webview#security + requirements: + - Use Content Security Policy in all webviews + - Sanitize user input to prevent XSS + - Use nonces for inline scripts + - Validate messages from webviews + - Store secrets securely using VS Code's SecretStorage API + - Disable insecure content in webviews + - Follow principle of least privilege + + accessibility: + platformStandard: "WCAG 2.1 AA" + requirements: + - Keyboard navigation support + - Screen reader compatibility + - High contrast theme support + - Focus indicators + - Semantic HTML in webviews + - ARIA labels where needed + documentation: https://code.visualstudio.com/api/extension-guides/accessibility + + manifest: + file: package.json + description: | + Every extension requires a package.json manifest defining: + - Extension metadata (name, version, publisher, description) + - Activation events (when extension loads) + - Contribution points (commands, views, languages, etc.) + - Dependencies and engines + - Extension capabilities and permissions + schema: + name: + type: string + required: true + description: Extension name (lowercase, no spaces) + displayName: + type: string + required: true + description: Human-readable display name + version: + type: string + required: true + description: Semantic version + publisher: + type: string + required: true + description: Publisher identifier + engines: + type: object + required: true + description: VS Code version compatibility + activationEvents: + type: array + required: false + description: Events that trigger extension activation + main: + type: string + required: false + description: Entry point for Extension Host code + contributes: + type: object + required: false + description: Contribution points (commands, views, etc.) + categories: + type: array + required: false + description: Extension categories for marketplace + icon: + type: string + required: false + description: Path to extension icon + + developmentTools: + - name: Extension Generator + description: Yeoman generator for scaffolding extensions + package: "generator-code" + command: "yo code" + url: https://github.com/microsoft/vscode-generator-code + + - name: vsce (Publishing Tool) + description: CLI for packaging and publishing extensions + package: "@vscode/vsce" + command: "vsce package / vsce publish" + url: https://github.com/microsoft/vscode-vsce + + - name: Extension Test Runner + description: Test framework for extensions + package: "@vscode/test-electron" + url: https://github.com/microsoft/vscode-test + + - name: Webview UI Toolkit Samples + description: Sample code and documentation + url: https://github.com/microsoft/vscode-webview-ui-toolkit-samples + + - name: Extension Samples Repository + description: Official extension samples + url: https://github.com/microsoft/vscode-extension-samples + + theming: + enabled: true + description: | + VS Code supports multiple color themes (light, dark, high contrast). + Extensions should respect the active theme. + implementation: + webviewSupport: true + cssVariables: true + themingApi: true + colorThemes: + - Light (Visual Studio) + - Dark (Visual Studio Dark) + - High Contrast Light + - High Contrast Dark + guidelines: + - Use CSS variables for theming in webviews + - Support all theme types + - Use theme colors from VS Code API + - Test in all theme modes + +notes: | + Visual Studio Code's Extension Platform provides a sophisticated dual-process + architecture that balances security, performance, and flexibility. + + Key characteristics: + - Extension Host: Node.js process for extension logic with full VS Code API + - Webview: Sandboxed iframe for custom UI with HTML/CSS/JS + - Communication: postMessage for Extension Host <-> Webview communication + - Webview UI Toolkit: Optional but recommended for consistent, themed UI + - Native Components: Tree views, status bar, quick picks rendered by VS Code + - Contribution Points: Extensive customization via package.json + - Security: Sandboxed webviews, CSP enforcement, marketplace review + + The architecture allows rich custom UIs while maintaining editor security and + performance. Extensions can choose between native VS Code components (tree views, + status bar) or fully custom webview UIs. + +metadata: + fenestra: + createdAt: "2025-12-30" + author: "Fenestra Specification Team" + category: "Development Tools" + tags: + - code-editor + - ide + - extensions + - webview + - desktop-app + relatedPlatforms: + - JetBrains IDE Plugins + - Eclipse Plugins + - Atom Packages + - Sublime Text Packages diff --git a/specs/fenestra/examples/0.1.0/zendesk.fenestra.yaml b/specs/fenestra/examples/0.1.0/zendesk.fenestra.yaml new file mode 100644 index 0000000..fb91834 --- /dev/null +++ b/specs/fenestra/examples/0.1.0/zendesk.fenestra.yaml @@ -0,0 +1,1298 @@ +# Fenestra Document: Zendesk Apps Framework +# +# Zendesk Apps Framework represents iframe-based apps with recommended +# component library. Apps run in sandboxed iframes and communicate via +# ZAFClient. Garden Design System (React) is strongly recommended. + +fenestra: "0.1.0" + +info: + title: Zendesk Apps Framework UI Ecosystem + version: "1.0.0" + description: | + Zendesk Apps Framework (ZAF) enables developers to extend Zendesk products + with custom apps running in sandboxed iframes. Apps communicate with the + host Zendesk product via the ZAFClient SDK for cross-frame messaging. + + Key characteristic: Apps run in iframes with ZAFClient REQUIRED for platform + communication. Garden Design System (React components) is RECOMMENDED for + consistent UI but not enforced. Developers can use their own components. + + contact: + name: Zendesk Developer Relations + url: https://developer.zendesk.com/ + email: developers@zendesk.com + +platform: + name: Zendesk + vendor: Zendesk, Inc. + documentation: https://developer.zendesk.com/documentation/apps/ + appMarketplace: https://www.zendesk.com/marketplace/ + developerPortal: https://apps.zendesk.com/ + changelog: https://developer.zendesk.com/documentation/apps/changelog/ + +sdks: + zaf-sdk: + name: Zendesk Apps Framework SDK + packageManager: npm + package: "zendesk_app_framework_sdk" + version: "^2.0.0" + repository: https://github.com/zendesk/zendesk_app_framework_sdk + documentation: https://developer.zendesk.com/api-reference/apps/apps-core-api/client_api/ + cdn: https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js + description: | + The ZAF SDK provides the ZAFClient for cross-frame communication between + your iframe app and the host Zendesk product. Enables event listening, + property access, and action invocation on the Zendesk platform. + exports: + ZAFClient: + type: class + description: | + Main client for communicating with Zendesk Apps Framework. + Initialize with ZAFClient.init() to establish connection. + init: + type: method + description: | + Initializes connection between app and ZAF platform. Returns + client instance for ongoing communication. Triggers app.registered + event when connection is established. + get: + type: method + description: Retrieves data from the Zendesk platform (ticket, user, context) + set: + type: method + description: Sets data on the Zendesk platform + invoke: + type: method + description: Invokes actions on the Zendesk platform (resize, modal, notify) + on: + type: method + description: Registers event listeners for platform events + request: + type: method + description: Makes HTTP requests with authentication handled by ZAF + metadata: + type: method + description: Retrieves app metadata and settings + context: + type: method + description: Gets current context (location, instanceGuid, account) + + garden-react: + name: Zendesk Garden React Components + packageManager: npm + package: "@zendeskgarden/react-components" + version: "^9.0.0" + repository: https://github.com/zendeskgarden/react-components + documentation: https://garden.zendesk.com/components/ + description: | + Garden is Zendesk's design system providing React components for + building consistent, accessible UIs. Components are published as + individual packages but can be used together seamlessly. + exports: + # Action Components + Button: + type: component + description: Primary action button with variants + package: "@zendeskgarden/react-buttons" + IconButton: + type: component + description: Button with icon only + package: "@zendeskgarden/react-buttons" + Anchor: + type: component + description: Styled link component + package: "@zendeskgarden/react-buttons" + + # Form Components + Input: + type: component + description: Text input field + package: "@zendeskgarden/react-forms" + Textarea: + type: component + description: Multi-line text input + package: "@zendeskgarden/react-forms" + Checkbox: + type: component + description: Checkbox input + package: "@zendeskgarden/react-forms" + Radio: + type: component + description: Radio button input + package: "@zendeskgarden/react-forms" + Toggle: + type: component + description: Toggle switch + package: "@zendeskgarden/react-forms" + Field: + type: component + description: Form field container with label and hint + package: "@zendeskgarden/react-forms" + + # Dropdown Components + Select: + type: component + description: Select dropdown (non-editable) + package: "@zendeskgarden/react-dropdowns" + Combobox: + type: component + description: Editable dropdown with autocomplete + package: "@zendeskgarden/react-dropdowns" + Menu: + type: component + description: Dropdown menu with items + package: "@zendeskgarden/react-dropdowns" + Autocomplete: + type: component + description: Autocomplete input + package: "@zendeskgarden/react-dropdowns" + + # Chrome Components (Layout) + Chrome: + type: component + description: Main application shell container + package: "@zendeskgarden/react-chrome" + Header: + type: component + description: Application header + package: "@zendeskgarden/react-chrome" + Nav: + type: component + description: Navigation container + package: "@zendeskgarden/react-chrome" + Body: + type: component + description: Main content body + package: "@zendeskgarden/react-chrome" + Footer: + type: component + description: Application footer + package: "@zendeskgarden/react-chrome" + + # Modal Components + Modal: + type: component + description: Modal dialog overlay + package: "@zendeskgarden/react-modals" + Drawer: + type: component + description: Slide-in drawer panel + package: "@zendeskgarden/react-modals" + TooltipModal: + type: component + description: Tooltip-style modal + package: "@zendeskgarden/react-modals" + + # Navigation Components + Tabs: + type: component + description: Tab navigation component + package: "@zendeskgarden/react-tabs" + Accordion: + type: component + description: Expandable/collapsible sections + package: "@zendeskgarden/react-accordions" + + # Notification Components + Notification: + type: component + description: Toast/banner notification + package: "@zendeskgarden/react-notifications" + Alert: + type: component + description: Alert message component + package: "@zendeskgarden/react-notifications" + Well: + type: component + description: Highlighted content container + package: "@zendeskgarden/react-notifications" + + # Data Display + Table: + type: component + description: Data table with sorting and selection + package: "@zendeskgarden/react-tables" + Avatar: + type: component + description: User avatar component + package: "@zendeskgarden/react-avatars" + Tag: + type: component + description: Tag/label component + package: "@zendeskgarden/react-tags" + Tooltip: + type: component + description: Tooltip overlay + package: "@zendeskgarden/react-tooltips" + + # Layout Components + Grid: + type: component + description: Responsive grid system + package: "@zendeskgarden/react-grid" + Pagination: + type: component + description: Pagination controls + package: "@zendeskgarden/react-pagination" + + # Loaders + Spinner: + type: component + description: Loading spinner + package: "@zendeskgarden/react-loaders" + Skeleton: + type: component + description: Skeleton placeholder + package: "@zendeskgarden/react-loaders" + Dots: + type: component + description: Dots loading indicator + package: "@zendeskgarden/react-loaders" + +componentCatalog: + categories: + action: + name: Actions + description: Interactive elements for user actions + components: [button, iconButton, anchor] + + input: + name: Form Inputs + description: Form controls for user input + components: [input, textarea, checkbox, radio, toggle, field] + + dropdown: + name: Dropdowns + description: Dropdown menus and select components + components: [select, combobox, menu, autocomplete] + + chrome: + name: Chrome (Layout) + description: Application shell and layout components + components: [chrome, header, nav, body, footer] + + overlay: + name: Overlays + description: Modal dialogs and overlays + components: [modal, drawer, tooltipModal, tooltip] + + navigation: + name: Navigation + description: Navigation and organization components + components: [tabs, accordion] + + notification: + name: Notifications + description: Alert and notification components + components: [notification, alert, well] + + dataDisplay: + name: Data Display + description: Components for displaying data + components: [table, avatar, tag] + + layout: + name: Layout + description: Grid and layout utilities + components: [grid, pagination] + + feedback: + name: Feedback + description: Loading and progress indicators + components: [spinner, skeleton, dots] + + components: + # ACTION COMPONENTS + button: + name: Button + description: | + Primary action button with multiple variants and sizes. + Supports default, primary, and basic types with optional danger styling. + category: action + sdkBinding: + sdk: garden-react + export: Button + package: "@zendeskgarden/react-buttons" + webStandardMapping: + htmlElement: button + ariaRole: button + semanticType: action + props: + size: + type: string + enum: [small, medium, large] + default: medium + description: Button size + isPrimary: + type: boolean + default: false + description: Primary button style (blue) + isBasic: + type: boolean + default: false + description: Basic button style (minimal) + isDanger: + type: boolean + default: false + description: Danger styling for destructive actions + isStretched: + type: boolean + default: false + description: Stretch to fill container width + disabled: + type: boolean + default: false + description: Disable the button + focusInset: + type: boolean + default: false + description: Inset focus indicator + variants: + - default + - primary + - basic + - danger + accessibility: + keyboardSupport: true + screenReaderSupport: true + labelRequired: true + examples: + - title: Primary Button + code: | + import { Button } from '@zendeskgarden/react-buttons'; + + + language: jsx + - title: Danger Button + code: | + import { Button } from '@zendeskgarden/react-buttons'; + + + language: jsx + + modal: + name: Modal + description: | + Modal dialog that overlays the page and blocks interaction with + the rest of the content. Available in default and large sizes. + category: overlay + sdkBinding: + sdk: garden-react + export: Modal + package: "@zendeskgarden/react-modals" + webStandardMapping: + htmlElement: dialog + ariaRole: dialog + semanticType: container + props: + isLarge: + type: boolean + default: false + description: Large modal size + focusOnMount: + type: boolean + default: true + description: Focus modal on mount + backdropProps: + type: object + description: Props for the backdrop element + onClose: + type: function + description: Callback when modal is closed + accessibility: + keyboardSupport: true + screenReaderSupport: true + focusTrap: true + escapeToClose: true + examples: + - title: Basic Modal + code: | + import { Modal, Header, Body, Footer, Close } from '@zendeskgarden/react-modals'; + import { Button } from '@zendeskgarden/react-buttons'; + + setIsOpen(false)}> +
Modal Title
+ Modal content goes here +
+ + +
+ +
+ language: jsx + + input: + name: Input + description: | + Text input field for user data entry. Should be nested within + a Field component for proper accessibility attributes. + category: input + sdkBinding: + sdk: garden-react + export: Input + package: "@zendeskgarden/react-forms" + webStandardMapping: + htmlElement: input + inputType: text + semanticType: input + props: + isCompact: + type: boolean + default: false + description: Compact sizing + isBare: + type: boolean + default: false + description: Remove borders and padding + focusInset: + type: boolean + default: false + description: Inset focus indicator + validation: + type: string + enum: [success, warning, error] + description: Validation state + accessibility: + labelRequired: true + keyboardSupport: true + screenReaderSupport: true + examples: + - title: Input with Label + code: | + import { Field, Label, Input, Hint } from '@zendeskgarden/react-forms'; + + + + Enter your email + + + language: jsx + + select: + name: Select + description: | + Non-editable dropdown select component. Use isMultiselectable + for multiple selections. For editable dropdowns, use Combobox. + category: dropdown + sdkBinding: + sdk: garden-react + export: Select + package: "@zendeskgarden/react-dropdowns" + webStandardMapping: + htmlElement: select + ariaRole: listbox + semanticType: input + props: + isMultiselectable: + type: boolean + default: false + description: Allow multiple selections + isCompact: + type: boolean + default: false + description: Compact sizing + disabled: + type: boolean + default: false + placeholder: + type: string + description: Placeholder text + accessibility: + keyboardSupport: true + screenReaderSupport: true + labelRequired: true + + chrome: + name: Chrome + description: | + Main application shell container that provides consistent layout + structure for Zendesk-style applications. + category: chrome + sdkBinding: + sdk: garden-react + export: Chrome + package: "@zendeskgarden/react-chrome" + webStandardMapping: + htmlElement: div + semanticType: container + props: + isFluid: + type: boolean + default: false + description: Fluid width layout + hue: + type: string + description: Color hue for theming + examples: + - title: Basic Chrome Layout + code: | + import { Chrome, Header, Nav, Body, Footer } from '@zendeskgarden/react-chrome'; + + +
Application Header
+ + Main Content +
Footer
+
+ language: jsx + + table: + name: Table + description: | + Data table component with support for sorting, selection, and + row reordering (via dnd-kit). Available in small, medium, and large sizes. + category: dataDisplay + sdkBinding: + sdk: garden-react + export: Table + package: "@zendeskgarden/react-tables" + webStandardMapping: + htmlElement: table + ariaRole: table + semanticType: data + props: + size: + type: string + enum: [small, medium, large] + default: medium + description: Table row size + isReadOnly: + type: boolean + default: false + description: Read-only mode (no hover states) + accessibility: + keyboardSupport: true + screenReaderSupport: true + captionRecommended: true + + notification: + name: Notification + description: | + Toast/banner notification for displaying messages to users. + Supports multiple types (success, warning, error, info). + category: notification + sdkBinding: + sdk: garden-react + export: Notification + package: "@zendeskgarden/react-notifications" + props: + type: + type: string + enum: [success, warning, error, info] + description: Notification type + placement: + type: string + enum: [top-start, top, top-end, bottom-start, bottom, bottom-end] + description: Notification placement + accessibility: + ariaRole: status + screenReaderSupport: true + +policies: + componentRequirement: + level: recommended + scope: all + rationale: | + Zendesk strongly recommends using Garden Design System components for + consistent UI, accessibility, and integration with Zendesk products. + However, component usage is not enforced - developers can use their + own components or frameworks while still communicating via ZAFClient. + + customComponents: + allowed: true + constraints: + - Apps must run in sandboxed iframe + - Must use ZAFClient SDK for platform communication + - Must respect iframe sandbox constraints + registrationRequired: false + approvalRequired: false + documentation: https://developer.zendesk.com/documentation/apps/app-developer-guide/using-the-apps-framework/ + rationale: | + Apps have freedom to use any UI framework (React, Vue, Angular, vanilla JS) + as long as they communicate via ZAFClient and follow security guidelines. + + publishing: + privateApps: + name: Private Apps + componentRequirement: recommended + customComponentsAllowed: true + reviewRequired: false + notes: | + Private apps for single Zendesk accounts. Garden recommended but + not required. No marketplace review needed. + + publicApps: + name: Public Apps + componentRequirement: recommended + customComponentsAllowed: true + reviewRequired: true + securityReviewRequired: true + notes: | + Apps distributed to multiple customers must be submitted to Marketplace + for security and compliance review. Must use global OAuth for auth. + requirements: + - Global OAuth authentication required + - Custom API headers required (X-Zendesk-Marketplace-*) + - Security review for data handling + - Privacy policy disclosure required + + marketplaceApps: + name: Marketplace Apps + componentRequirement: recommended + customComponentsAllowed: true + certificationRequired: false + reviewRequired: true + securityReviewRequired: true + notes: | + Apps listed in Zendesk Marketplace undergo comprehensive review + including security, functionality, and compliance verification. + requirements: + - Must include X-Zendesk-Marketplace-Name header + - Must include X-Zendesk-Marketplace-Organization-Id header + - Must include X-Zendesk-Marketplace-App-Id header + - Data handling disclosure required + - Privacy policy and terms of service required + - OAuth scope audit + - API security verification + + designGuidelines: + required: false + designSystem: "Zendesk Garden" + designSystemUrl: https://garden.zendesk.com/ + designTokensProvided: true + guidelines: + - Use Garden components for consistent UI (recommended) + - Follow accessibility best practices (WCAG 2.1 AA) + - Provide clear labels and helper text + - Use validation states appropriately + - Ensure keyboard navigation support + - Test in different iframe contexts + + security: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + - allow-popups + secureSettings: + enabled: true + description: | + Use secure settings for sensitive data like API tokens or passwords. + Secure settings are encrypted and cannot be read by the app - they + can only be used as placeholders replaced by the server. + domainWhitelist: required + authentication: + globalOAuth: required + apiTokens: prohibited + notes: | + Public apps must use global OAuth access tokens. API tokens or + regular OAuth tokens are prohibited per Zendesk Developer Terms. + +extensionPoints: + - id: ticket-sidebar + name: Ticket Sidebar + type: panel + extensionType: iframe + description: | + Panel on the right side of the ticket in the agent interface. + Primary location for ticket-related app functionality. + supportedComponents: + - all + constraints: + defaultWidth: 320 + flexible: true + autoLoad: optional + autoHide: optional + configuration: + flexible: + type: boolean + default: true + description: | + If true, iframe automatically resizes to match app tray width. + If false, iframe stays fixed at 320px width. + autoLoad: + type: boolean + default: true + description: Automatically load app when ticket opens + autoHide: + type: boolean + default: false + description: Hide app by default until clicked + context: + provides: + - ticket + - user + - currentUser + - organization + - group + - locale + - instances + actions: + - resize + - invoke + - get + - set + - request + - notify + events: + - ticket.save + - ticket.updated + - ticket.submit.start + - ticket.submit.done + - app.activated + - app.deactivated + - app.registered + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/ticket_sidebar/ + + - id: new-ticket-sidebar + name: New Ticket Sidebar + type: panel + extensionType: iframe + description: | + Panel on the right side of the new ticket interface. Similar to + ticket sidebar but for new ticket creation flow. + supportedComponents: + - all + constraints: + defaultWidth: 320 + flexible: true + autoLoad: optional + context: + provides: + - ticket + - user + - currentUser + - locale + actions: + - resize + - invoke + - get + - set + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/ticket_sidebar/ + + - id: nav-bar + name: Navigation Bar + type: panel + extensionType: iframe + description: | + Icon in the left navigation bar. Opens a modal or panel when clicked. + Good for app functionality not tied to specific tickets. + supportedComponents: + - all + constraints: + iconRequired: true + responsive: true + configuration: + icon: + type: string + required: true + description: Icon to display in nav bar + url: + type: string + description: URL to load in iframe + context: + provides: + - currentUser + - locale + - instances + actions: + - resize + - invoke + - get + - request + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/nav_bar/ + + - id: top-bar + name: Top Bar + type: panel + extensionType: iframe + description: | + Panel in the top bar of the agent interface. Can be always visible + or triggered by an icon. Supports custom sizing. + supportedComponents: + - all + constraints: + maxWidth: 600 + maxHeight: 600 + responsive: true + autoHide: optional + configuration: + autoHide: + type: boolean + default: false + description: Hide by default, show on icon click + url: + type: string + description: URL to load in iframe + size: + type: object + properties: + width: + type: string + description: Width in px or % + height: + type: string + description: Height in px or % + context: + provides: + - currentUser + - locale + - instances + actions: + - resize + - invoke + - get + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/top_bar/ + + - id: modal + name: Modal Dialog + type: modal + extensionType: iframe + description: | + Modal overlay opened programmatically via client.invoke('instances.create'). + Good for focused tasks or data collection workflows. + supportedComponents: + - all + constraints: + maxWidth: 800 + maxHeight: 600 + responsive: true + configuration: + url: + type: string + description: URL to load in modal iframe + size: + type: object + properties: + width: + type: string + height: + type: string + context: + provides: + - context + - currentUser + - locale + actions: + - close + - resize + - get + - invoke + invocation: + method: client.invoke('instances.create') + parameters: + location: modal + url: string + size: object + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/modal/ + + - id: background + name: Background + type: service + extensionType: iframe + description: | + Background app with no UI. Runs invisibly to handle events and + perform server-side operations. Useful for webhooks and automation. + supportedComponents: + - none (no UI) + constraints: + noUI: true + eventsOnly: true + context: + provides: + - currentUser + - locale + - account + actions: + - get + - request + - invoke + events: + - ticket.save + - ticket.updated + - app.activated + - app.registered + notes: | + Background apps don't have a visible UI. They respond to platform + events like ticket.save (server-side completion) and can perform + automated actions or integrations. + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/background/ + + - id: organization-sidebar + name: Organization Sidebar + type: panel + extensionType: iframe + description: | + Panel on the organization page, similar to ticket sidebar but + for organization-related functionality. + supportedComponents: + - all + constraints: + defaultWidth: 320 + flexible: true + context: + provides: + - organization + - currentUser + - locale + actions: + - resize + - get + - invoke + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/organization_sidebar/ + + - id: user-sidebar + name: User Sidebar + type: panel + extensionType: iframe + description: | + Panel on the user profile page for user-specific app features. + supportedComponents: + - all + constraints: + defaultWidth: 320 + flexible: true + context: + provides: + - user + - currentUser + - locale + actions: + - resize + - get + - invoke + documentation: https://developer.zendesk.com/api-reference/apps/apps-support-api/user_sidebar/ + +renderingEngines: + iframe-sandbox: + type: custom + name: Sandboxed IFrame + description: | + Apps run in sandboxed iframes with restricted permissions. + Communication with the host Zendesk product happens via ZAFClient + using secure cross-frame messaging (postMessage). + sandboxing: + iframeSandbox: true + sandboxAttributes: + - allow-scripts + - allow-forms + - allow-same-origin + - allow-popups + crossFrameMessaging: postMessage + securityModel: | + Apps are isolated in iframes and can only interact with Zendesk + via the ZAFClient SDK. This ensures security and prevents direct + DOM access to the host application. + + any-framework: + type: custom + name: Any JavaScript Framework + description: | + Developers can use any frontend framework (React, Vue, Angular, + Svelte, vanilla JS) inside the iframe as long as they integrate + with ZAFClient for platform communication. + frameworks: + - React (recommended with Garden) + - Vue + - Angular + - Svelte + - Vanilla JavaScript + - Any framework that can run in a browser iframe + +jsonFormsIntegration: + supported: true + rendererSet: custom + customRenderersAllowed: true + notes: | + Developers can integrate JSON Forms with Garden component renderers + or custom renderers within their iframe apps. + +mcpAppsIntegration: + supported: false + notes: "Potential future integration via iframe embedding" + +extensionType: iframe + +extensions: + i18n: + enabled: true + localeDetection: automatic + description: | + Zendesk Apps Framework provides automatic locale detection via + ZAFClient. Apps can localize content using translation JSON files + in the translations folder with data-i18n-key attributes. + implementation: + translationFiles: + location: translations/ + format: json + naming: "{locale}.json" + example: | + translations/en.json: + { "default": { "hello_world": "Hello World!" }} + + translations/fr.json: + { "default": { "hello_world": "Bonjour le Monde!" }} + htmlIntegration: + attribute: data-i18n-key + description: | + Add data-i18n-key attribute to HTML elements. The framework + replaces element text with the corresponding translation string + based on user locale. + example: + fallbackBehavior: + defaultLocale: en + description: Falls back to English if user locale not available + clientProvides: + - currentUser.locale + - currentAccount.locale + developerResponsibility: + - Create translation files for supported locales + - Add data-i18n-key attributes to HTML elements + - Handle locale-specific date/time formatting + - Support RTL languages if needed + supportedLocales: + - en-US (English - United States) + - en-GB (English - United Kingdom) + - de (German) + - es (Spanish) + - es-419 (Spanish - Latin America) + - fr (French) + - fr-ca (French - Canada) + - it (Italian) + - ja (Japanese) + - ko (Korean) + - nl (Dutch) + - pl (Polish) + - pt-br (Portuguese - Brazil) + - pt (Portuguese) + - ru (Russian) + - sv (Swedish) + - tr (Turkish) + - zh-cn (Chinese - Simplified) + - zh-tw (Chinese - Traditional) + - da (Danish) + - fi (Finnish) + - no (Norwegian) + - cs (Czech) + - id (Indonesian) + - th (Thai) + - ar (Arabic) + - he (Hebrew) + documentation: https://developer.zendesk.com/documentation/apps/build-an-app/localizing-a-support-app/ + + compliance: + enabled: true + description: | + Apps distributed to multiple Zendesk customers must comply with + Marketplace security requirements, data handling policies, and + authentication standards. + requirements: + securityReview: + required: true + scope: publicDistribution + includes: + - Data handling and privacy review + - OAuth implementation verification + - Secure API usage patterns + - Permission scope audit + - Custom header verification + documentation: https://developer.zendesk.com/documentation/marketplace/ + functionalReview: + required: true + scope: marketplaceApps + includes: + - App functionality testing + - Error handling validation + - User experience assessment + - Performance testing + contentReview: + required: true + scope: marketplaceApps + includes: + - App listing content accuracy + - Screenshots and media quality + - Privacy policy completeness + - Terms of service clarity + authenticationRequirements: + globalOAuth: required + apiTokens: prohibited + scope: publicApps + description: | + Public apps must use global OAuth access tokens. API tokens + and regular OAuth tokens are prohibited for apps distributed + to multiple customers. + documentation: https://developer.zendesk.com/api-reference/introduction/security-and-auth/ + apiHeaderRequirements: + required: true + scope: marketplaceApps + headers: + X-Zendesk-Marketplace-Name: + required: true + description: Name of the integration (can change) + X-Zendesk-Marketplace-Organization-Id: + required: true + description: Organization ID from developer portal (static) + X-Zendesk-Marketplace-App-Id: + required: true + description: App ID assigned when submitted + notes: | + Custom headers verified during submission process. Required for + all external API requests from marketplace apps. + documentation: https://developer.zendesk.com/documentation/marketplace/building-a-marketplace-app/request-header-requirements-for-marketplace-apps/ + dataHandling: + disclosureRequired: true + description: | + Apps must disclose what Zendesk data they access and for what + purpose. Must follow data protection and privacy regulations. + constraints: + - No unauthorized data sharing + - Secure data storage + - Compliance with GDPR, CCPA, etc. + - Customer data isolation + secureSettings: + enabled: true + description: | + Use secure settings in manifest.json for sensitive data. + Secure settings are encrypted and can only be used as + server-side placeholders, not read by client code. + domainWhitelist: required + bestPractices: + - Never expose API tokens in client code + - Use secure settings with domainWhitelist + - Don't attempt to read secure settings (won't work) + certifications: + marketplaceListing: + available: true + description: Apps approved for Marketplace listing + securityCompliance: + available: true + description: Security and compliance verification + documentation: https://support.zendesk.com/hc/en-us/articles/9590471542170 + guidelines: https://developer.zendesk.com/documentation/marketplace/building-a-marketplace-app/ + + analytics: + enabled: true + description: | + Zendesk provides analytics for marketplace apps including + installation metrics, usage data, and performance monitoring + through the developer portal. + metrics: + - Active installations + - User engagement + - API usage + - Error rates + - Performance metrics + dashboard: https://apps.zendesk.com/ (Developer Portal) + + testing: + enabled: true + description: Tools and methods for testing Zendesk apps + tools: + zcli: + name: Zendesk CLI + description: Command-line tool for app development and testing + features: + - Local app server for development + - App packaging and validation + - App deployment to Zendesk instances + - Manifest validation + installation: npm install -g @zendesk/zcli + documentation: https://developer.zendesk.com/documentation/apps/getting-started/using-zcli/ + localTesting: + description: | + Use ZCLI server to run app locally and test in Zendesk + products with live reloading and debugging. + command: zcli apps:server + validation: + manifestValidation: true + translationValidation: true + securityValidation: true + documentation: https://developer.zendesk.com/documentation/apps/app-developer-guide/build-and-test-your-app/ + + accessibilityFeatures: + keyboardNavigation: true + screenReaderSupport: true + highContrastMode: true + description: | + Garden components are built with accessibility in mind, following + WCAG 2.1 AA standards. Apps using Garden inherit these features. + guidelines: + - Use semantic HTML elements + - Provide ARIA labels where needed + - Ensure keyboard navigation works + - Test with screen readers + - Support high contrast modes + - Maintain adequate color contrast + - Provide focus indicators + documentation: https://garden.zendesk.com/components/ + + rateLimits: + description: Rate limits for Zendesk API requests + limits: + standard: + rate: 200 requests per minute per account + description: Standard API rate limit + concurrent: + rate: 5 concurrent requests per account + description: Maximum concurrent requests + search: + rate: 60 requests per minute + description: Search API specific limit + documentation: https://developer.zendesk.com/api-reference/introduction/rate-limits/ + + securityFeatures: + oauthRequired: true + scopedPermissions: true + iframeSandbox: true + description: | + Zendesk apps use OAuth for authentication with granular permission + scopes. Apps run in sandboxed iframes with controlled communication + via ZAFClient. Secure settings protect sensitive data. + features: + - OAuth 2.0 authentication + - Granular permission scopes + - Sandboxed iframe execution + - Secure settings encryption + - Domain whitelisting + - Request signing for marketplace apps + - HTTPS required for production + documentation: https://developer.zendesk.com/api-reference/introduction/security-and-auth/ + +notes: | + Zendesk Apps Framework provides a flexible iframe-based extension model + where apps run in sandboxed iframes and communicate with the host Zendesk + product via the ZAFClient SDK. + + Key characteristics: + - Iframe-based: Apps run in sandboxed iframes with controlled communication + - ZAFClient required: All platform interaction goes through ZAFClient SDK + - Garden recommended: Garden Design System strongly recommended but not enforced + - Framework agnostic: Use any frontend framework (React, Vue, Angular, etc.) + - Multiple locations: Apps can appear in sidebar, nav bar, top bar, modal, background + - Secure by default: OAuth, sandboxing, secure settings, domain whitelisting + - I18n support: Built-in locale detection and translation system + - Marketplace ready: Comprehensive review process for public apps + + Apps have complete freedom in their UI implementation while maintaining + security through iframe sandboxing and ZAFClient communication protocol. + Garden components are strongly recommended for consistency with Zendesk UI + and built-in accessibility, but developers can choose their own approach. + +metadata: + fenestra: + createdAt: "2025-12-30" + author: "Fenestra Specification Team" + category: "Customer Service Platform" + tags: + - customer-service + - help-desk + - iframe + - react + - garden + - zaf + relatedPlatforms: + - Miro (iframe with optional components) + - Salesforce (Lightning Web Components) + - Intercom (iframe-based apps)