Done. Synced 247 contacts in 412 ms.
Ada Tan
CEO · Mariposa Labs ·
The developer toolkit for HubSpot — syncs, UI extensions, agent tools, and a runtime you own.
One install. The whole toolkit.
CEO · Mariposa Labs ·
Done. Synced 247 contacts in 412 ms.
Deployed in 1.2 s · 124 KiB.
Quote PDF sent · stage → Proposal.
7 active hooks · 1.2k events / day.
Generates a branded quote PDF from the deal record and emails it to the primary contact. Advances stage on send.
412 ms · 247 rows
deployed
184 ms
1.2 s
CEO · Mariposa Labs · ada@mariposalabs.io
Synced 247 contacts in 412 ms.
Deployed in 1.2 s · 124 KiB.
Quote PDF sent · stage → Proposal.
7 active hooks · 1.2k events / day.
Point a Worker at any API and its records land as Contacts, Companies, or any custom object, then stay current on a schedule. Cursors, identity matching, retries, and drift detection are handled for you. You write the fetch.
import { defineSource, defineWorker } from "@hs-x/sdk"; const airtableContacts = defineSource({ name: "airtableContacts", auth: { type: "bearer", token: process.env.AIRTABLE_TOKEN }, async fetch({ cursor, http }) { const res = await http.get("https://api.airtable.com/v0/appXYZ/Contacts", { query: { pageSize: 100, offset: cursor }, }); return { cursor: res.body.offset, rows: res.body.records.map(r => ({ key: r.fields.Email, data: { email: r.fields.Email, lifecycle_stage: r.fields.Stage, annual_revenue: r.fields.ARR, owner: r.fields.OwnerEmail, }, })), }; }, }); const worker = defineWorker("contacts"); worker.sync(airtableContacts, { into: "contacts", schedule: "5m", schema: { email: "email", lifecycle_stage: { type: "enum", values: ["subscriber", "lead", "customer"] }, annual_revenue: "currency", owner: "user", }, }); export default worker;
hs-uix gives you React components that match HubSpot's look, typed from your portal's own schema. Every app card gets a backend in your Cloudflare — same types end to end, no glue code, and streaming responses for the slow work.
import { DataTable } from "hs-uix/datatable"; import { KeyValueList, SectionHeader } from "hs-uix/common-components"; import { formatCurrency } from "hs-uix/utils"; import { Tile, hubspot } from "@hubspot/ui-extensions"; function ContactPanel({ context, runServerless }) { return ( <Tile> <SectionHeader title="Properties" /> <KeyValueList items={[ { label: "Lifecycle", value: "Customer" }, { label: "Annual revenue", value: formatCurrency(184000) }, { label: "Owner", value: "Carter McKay" }, ]} /> <SectionHeader title="Open deals" /> <DataTable columns={[ { id: "name", label: "Deal", sortable: true }, { id: "amount", label: "Amount", format: "currency" }, { id: "stage", label: "Stage", filter: "enum" }, ]} fetch={() => runServerless({ name: "listDeals", parameters: { contactId: context.crm.objectId } })} /> </Tile> ); } hubspot.extend(() => <ContactPanel />);
One TypeScript function becomes an agent tool Breeze can call and a custom workflow action your team can drop into any workflow — same code, same auth. Coding agents can exercise it locally through the HS-X MCP server's invoke tool while you build.
worker.tool("createQuote", { label: "Create quote", description: "Generate a quote PDF and email it to the primary contact.", objectType: "deal", input: { template: { type: "enum", values: ["standard", "saas"] }, }, agent: { description: "Create and send a quote for this deal.", expose: ["template"], }, async handler({ input, enrolledObject, hubspot }) { const pdf = await renderQuote(enrolledObject, input.template); await hubspot.crm.objects.emails.basicApi.create({ /* … */ }); return { message: `Quote sent for deal ${enrolledObject.id}.` }; }, });
Set up a webhook subscription for deal-stage changes, form submissions, any HubSpot event — and run a handler on your runtime. We verify every signature, drop duplicate deliveries, and queue the flood when HubSpot pushes faster than you can handle. You write the handler.
Your code, data, and customers' tokens live in a Cloudflare account you own — Workers, Durable Objects, Queues, KV, D1, all of it. A deploy needs only your HubSpot and Cloudflare tokens — no hs-x account required. If hs-x disappeared tomorrow, every deployed app would keep running.
That's the whole setup, exactly as shown: export two tokens and run hs-x deploy. No signup, no dashboard — the Unlinked deploy id in the log is the proof. Start without an account →
One toolchain. A CLI for you. An SDK that's just TypeScript. An MCP server so your coding agent can do everything you can. A REST API for everything else. Same types, same project, same deploy.
Scaffold, deploy, tail logs, manage portals. Token-efficient — coding agents can drive it without burning context.
$ npm i -g @hs-x/cli $ hs-x init my-portal $ hs-x deployRead the CLI docs →
Syncs, workflow actions, triggers, UI extensions — declared in plain TypeScript with a schema that types the rest of your code for you.
import { defineSource, defineWorker } from "@hs-x/sdk"; const airtable = defineSource({ … }); const worker = defineWorker("contacts"); worker.sync(airtable, { into: "contacts", … }); export default worker;Read the SDK docs →
An MCP server for your coding agent — validate the project, list capabilities, invoke any handler through the same dispatch path production uses.
$ claude mcp add hs-x -- \ npx -y @hs-x/mcp
$ codex mcp add hs-x -- \ npx -y @hs-x/mcp
// .cursor/mcp.json { "mcpServers": { "hs-x": { "command": "npx", "args": ["-y", "@hs-x/mcp"] } } }
// opencode.json { "mcp": { "hs-x": { "type": "local", "command": ["npx", "-y", "@hs-x/mcp"] } } }Read the MCP spec →
The same control plane the CLI and MCP speak — projects, deploys, revisions, rollbacks. PATs with deploy, read, and admin scopes, and an account audit log.
POST /v1/deploys/plan GET /v1/projects/{id}/revisions POST /v1/projects/{id}/rollbackSee the control-plane protocol →
hs-x handles the hard platform plumbing — types, deploys, token storage, per-portal rate limits, audit logs. HubSpot owns the portal. You own the Cloudflare account it all runs on, and every deploy writes a plain wrangler.toml you can ship without us. No lock-in by design.
Need it built? The team behind hs-x ships HubSpot work on hs-x — marketplace apps, syncs, agent tools, card migrations. Retainer or by the project.
Scaffold an app, wire a workflow action to an agent tool, watch Breeze call it against a developer test account. All from hs-x init.