From data
Generate typed data contracts from an OpenAPI spec so a UI agent can build data-driven interfaces without Claude ever seeing the underlying data. Triggers: "data contract", "API schema for UI", "wire up the API", "generate types from OpenAPI", "connect UI to API", "API integration layer" Use when the user wants Claude to understand an API's shape and produce typed interfaces, endpoint metadata, or fetch blueprints that a separate generative-UI agent can consume. Claude reads the OpenAPI spec, extracts endpoint signatures and response schemas, and outputs data contracts — never making live API calls or accessing real data.
npx claudepluginhub tmorrowdev/tmorrow_ai --plugin dataThis skill uses the workspace's default tool permissions.
Generate typed data contracts from your company's OpenAPI spec so a separate UI agent can build data-driven interfaces — without Claude ever seeing the actual data.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Builds scalable data pipelines, modern data warehouses, and real-time streaming architectures using Spark, dbt, Airflow, Kafka, and cloud platforms like Snowflake, BigQuery.
Builds production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. For data pipelines, workflow orchestration, and batch job scheduling.
Generate typed data contracts from your company's OpenAPI spec so a separate UI agent can build data-driven interfaces — without Claude ever seeing the actual data.
Your company exposes data through a core API service with an OpenAPI/Swagger spec. A separate generative-UI agent builds the frontend. This skill bridges the two:
Claude never sees or handles real data. It only works with the API's shape.
Fetch the spec from the documented URL endpoint. Parse it as JSON or YAML.
GET /openapi.json
— or —
GET /api/docs/swagger.json
Ask the user for the spec URL if not already known. Only read the schema — do not call any data endpoints.
What to extract:
info: API title, version, descriptionservers: Base URL(s) and environment labelspaths: Every endpoint with method, path, parameters, and response schemascomponents/schemas: Reusable data models (the core of the contracts)securitySchemes: Auth method (OAuth2 flows, scopes)Build a structured catalog of every endpoint relevant to the UI:
interface EndpointCatalog {
[operationId: string]: {
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
path: string;
summary: string;
parameters: ParameterDef[];
requestBody?: SchemaRef;
response: SchemaRef;
auth: AuthRequirement;
tags: string[];
};
}
Group endpoints by tag or domain (e.g., "users", "orders", "analytics").
For each endpoint (or group of related endpoints), produce a data contract — a self-contained typed interface the UI agent can use.
/**
* Data Contract: [Domain / Feature Name]
* Source: [METHOD] [path]
* Auth: OAuth2 — scopes: [list scopes]
* Last generated from spec version: [version]
*/
// --- Request ---
interface [OperationId]Request {
// Path parameters
// Query parameters
// Request body fields
}
// --- Response ---
interface [OperationId]Response {
// Top-level response fields
}
// --- Nested types ---
interface [NestedModel] {
// Fields from components/schemas
}
// --- Fetch blueprint ---
const endpoint = {
method: '[METHOD]',
path: '[path with {param} placeholders]',
auth: 'oauth2',
scopes: ['scope1', 'scope2'],
pagination?: {
style: 'offset' | 'cursor',
params: { limit: 'limit', offset: 'offset' | cursor: 'cursor' },
},
};
nullable: true, the type must be T | null.$ref chains. Resolve all $ref pointers into concrete types so the contract is self-contained.enum values, define them as a union type.? for optional fields in TypeScript.description from the spec as JSDoc comments.Deliver contracts in one of these formats depending on what the UI agent expects:
TypeScript interfaces (default):
contracts/
├── index.ts # Re-exports all contracts
├── users.contracts.ts # User-related endpoint contracts
├── orders.contracts.ts # Order-related endpoint contracts
├── analytics.contracts.ts
└── _shared.ts # Shared/reusable types (pagination, error shapes)
JSON Schema (if the UI agent prefers schema over types):
{
"operationId": "listUsers",
"method": "GET",
"path": "/api/v1/users",
"request": { /* JSON Schema for params */ },
"response": { /* JSON Schema for response body */ },
"auth": { "type": "oauth2", "scopes": ["users:read"] }
}
Before handing off:
$ref pointers are resolved (no dangling references)The API uses OAuth2. Contracts should document the auth requirement but never include tokens or credentials. The UI agent handles the auth flow at runtime.
Include in each contract:
const auth = {
type: 'oauth2',
flow: 'authorization_code', // or 'client_credentials', etc.
scopes: ['required:scope'],
tokenEndpoint: '/oauth/token', // from securitySchemes
authorizeEndpoint: '/oauth/authorize',
};
The UI agent needs to ask "what data is available?" before it can build anything. This section defines a discovery protocol so the two agents can coordinate without the user manually bridging them.
When asked "what data is available?", produce this catalog from the OpenAPI spec:
interface DataSourceCatalog {
apiName: string; // from spec info.title
apiVersion: string; // from spec info.version
baseUrl: string; // from spec servers[0].url
domains: DataDomain[];
}
interface DataDomain {
/** Domain name derived from OpenAPI tags (e.g., "Orders", "Users", "Analytics") */
name: string;
/** Human-readable description of what data this domain covers */
description: string;
/** Icon hint for the UI agent (e.g., "chart-bar", "users", "shopping-cart") */
iconHint: string;
/** Number of endpoints in this domain */
endpointCount: number;
/** High-level summary of what the user can explore */
capabilities: string[];
/** The data shapes available (table-like summaries for the user to browse) */
availableViews: DataView[];
}
interface DataView {
/** Human-readable label (e.g., "Order History", "Monthly Revenue") */
label: string;
/** What kind of data this returns */
type: 'list' | 'detail' | 'aggregate' | 'time-series' | 'search';
/** The operationId from the spec — used to request the full contract later */
operationId: string;
/** Key fields the user would see (column-like summary) */
fields: { name: string; type: string; description: string }[];
/** Available filters the user can apply */
filters: { name: string; type: string; description: string; options?: string[] }[];
/** Whether the endpoint supports pagination */
paginated: boolean;
}
When the data agent reads the spec, it might produce:
{
"apiName": "Acme Data Platform",
"apiVersion": "2.1.0",
"baseUrl": "https://api.acme.com/v2",
"domains": [
{
"name": "Orders",
"description": "Customer orders, line items, and fulfillment status",
"iconHint": "shopping-cart",
"endpointCount": 5,
"capabilities": [
"Browse order history with filters",
"View individual order details",
"Aggregate order metrics by time period",
"Search orders by customer or product"
],
"availableViews": [
{
"label": "Order History",
"type": "list",
"operationId": "listOrders",
"fields": [
{ "name": "orderId", "type": "string", "description": "Unique order identifier" },
{ "name": "customerName", "type": "string", "description": "Customer display name" },
{ "name": "total", "type": "number", "description": "Order total in USD" },
{ "name": "status", "type": "enum", "description": "Current order status" },
{ "name": "createdAt", "type": "datetime", "description": "When the order was placed" }
],
"filters": [
{ "name": "status", "type": "enum", "description": "Filter by status", "options": ["pending", "shipped", "delivered", "cancelled"] },
{ "name": "dateRange", "type": "date-range", "description": "Filter by order date" },
{ "name": "minTotal", "type": "number", "description": "Minimum order amount" }
],
"paginated": true
},
{
"label": "Revenue Over Time",
"type": "time-series",
"operationId": "getRevenueTimeSeries",
"fields": [
{ "name": "period", "type": "date", "description": "Time bucket" },
{ "name": "revenue", "type": "number", "description": "Total revenue" },
{ "name": "orderCount", "type": "number", "description": "Number of orders" }
],
"filters": [
{ "name": "granularity", "type": "enum", "description": "Time granularity", "options": ["day", "week", "month"] },
{ "name": "dateRange", "type": "date-range", "description": "Date window" }
],
"paginated": false
}
]
}
]
}
Step 1 — User or UI agent asks what's available:
"What data sources can I work with?"
Step 2 — Data agent produces the catalog:
Read the OpenAPI spec, group endpoints by tag, and produce the DataSourceCatalog structure above. Each domain becomes a card or section the UI agent can render.
Step 3 — UI agent renders selectable options: The UI agent takes the catalog and shows the user a menu of domains and views — cards, a sidebar, a dropdown, whatever suits the UI pattern.
Step 4 — User selects a view:
"I want to see Order History" (or clicks the card)
Step 5 — Data agent generates the full contract:
Using the operationId from the selected view, generate the complete data contract (request interface, response interface, fetch blueprint, auth, pagination) as defined in Phase 3 above.
Step 6 — UI agent builds the component: The UI agent receives the contract and builds a table, chart, or dashboard component that fetches data at runtime via the API. Claude never sees the actual data.
version field, include it in the catalog so the UI agent can detect stale contractsThe UI agent is a separate system that receives these contracts and builds components. Claude's job is to give it everything it needs to know about the API without any ambiguity:
The UI agent handles rendering, state management, and user interaction. Claude handles API comprehension, discovery, and contract generation.
User: "What data sources are available?"
→ Claude reads the OpenAPI spec, groups endpoints by tag, and produces a DataSourceCatalog the UI agent renders as selectable cards.
User: "Show me the order analytics view"
→ The UI agent passes the selected operationId back. Claude generates the full contract for that endpoint, and the UI agent builds the component.
User: "Generate data contracts for our user management endpoints" → Claude fetches the OpenAPI spec, filters to user-related paths, and produces TypeScript interfaces for list/get/search users with request params and response types.
User: "What endpoints are available for the analytics domain?"
→ Claude reads the spec, filters by the analytics tag, and presents a summary table of endpoints with their purpose, parameters, and response shapes.
User: "The UI agent needs to build a dashboard showing order metrics — what contracts does it need?" → Claude identifies the relevant order/analytics endpoints, generates contracts for each, includes pagination and filtering patterns, and bundles them as a handoff package.
x- extensions (custom vendor fields), include them in contracts as metadataoneOf / anyOf / allOf, resolve them into a clear discriminated union