Skip to content
Back to skills

Hubspot Local Dev Loop

ASecurity

'Configure HubSpot local development with testing and sandbox accounts.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
testingtypescriptbashnodenodejstestinggitapidocumentation

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add pauldx/claudifying --skill hubspot-local-dev-loop --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Hubspot Local Dev Loop?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Hubspot Local Dev Loop
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pauldx-hubspot-local-dev-loop/badge)](https://www.skillsdirectory.com/skills/pauldx-hubspot-local-dev-loop)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: hubspot-local-dev-loop
description: 'Configure HubSpot local development with testing and sandbox accounts.

  Use when setting up a development environment, mocking HubSpot APIs,

  or establishing a fast iteration cycle for HubSpot integrations.

  Trigger with phrases like "hubspot dev setup", "hubspot local development",

  "hubspot test sandbox", "develop with hubspot", "mock hubspot".

  '
allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Grep
version: 1.0.0
license: MIT
tags:
- saas
- crm
- marketing
- hubspot
compatibility: Designed for Claude Code
---
# HubSpot Local Dev Loop

## Overview

Set up a fast local development workflow for HubSpot integrations with sandbox accounts, mocking, and test utilities.

## Prerequisites

- Completed `hubspot-install-auth` setup
- Node.js 18+ with npm/pnpm
- HubSpot developer test account (free at developers.hubspot.com)

## Instructions

### Step 1: Create Project Structure

```
my-hubspot-project/
├── src/
│   ├── hubspot/
│   │   ├── client.ts       # Singleton @hubspot/api-client wrapper
│   │   ├── contacts.ts     # Contact operations
│   │   ├── deals.ts        # Deal operations
│   │   └── types.ts        # HubSpot type definitions
│   └── index.ts
├── tests/
│   ├── mocks/
│   │   └── hubspot.ts      # Shared mock factory
│   ├── contacts.test.ts
│   └── deals.test.ts
├── .env.local               # Local secrets (git-ignored)
├── .env.example             # Template for team
├── tsconfig.json
└── package.json
```

### Step 2: Create Client Singleton

```typescript
// src/hubspot/client.ts
import * as hubspot from '@hubspot/api-client';

let instance: hubspot.Client | null = null;

export function getHubSpotClient(): hubspot.Client {
  if (!instance) {
    if (!process.env.HUBSPOT_ACCESS_TOKEN) {
      throw new Error('HUBSPOT_ACCESS_TOKEN environment variable is required');
    }
    instance = new hubspot.Client({
      accessToken: process.env.HUBSPOT_ACCESS_TOKEN,
      numberOfApiCallRetries: 3,
    });
  }
  return instance;
}

// Reset client (useful for tests)
export function resetHubSpotClient(): void {
  instance = null;
}
```

### Step 3: Configure Testing with Vitest

```json
{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:integration": "HUBSPOT_TEST=true vitest --config vitest.integration.config.ts"
  },
  "devDependencies": {
    "@hubspot/api-client": "^13.0.0",
    "vitest": "^2.0.0",
    "tsx": "^4.0.0"
  }
}
```

### Step 4: Mock HubSpot API for Unit Tests

```typescript
// tests/mocks/hubspot.ts
import { vi } from 'vitest';

export function createMockHubSpotClient() {
  return {
    crm: {
      contacts: {
        basicApi: {
          create: vi.fn().mockResolvedValue({
            id: '101',
            properties: { firstname: 'Jane', lastname: 'Doe', email: 'jane@test.com' },
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
            archived: false,
          }),
          getById: vi.fn().mockResolvedValue({
            id: '101',
            properties: { firstname: 'Jane', lastname: 'Doe', email: 'jane@test.com' },
          }),
          getPage: vi.fn().mockResolvedValue({
            results: [],
            paging: undefined,
          }),
          update: vi.fn().mockResolvedValue({ id: '101', properties: {} }),
          archive: vi.fn().mockResolvedValue(undefined),
        },
        searchApi: {
          doSearch: vi.fn().mockResolvedValue({ total: 0, results: [] }),
        },
        batchApi: {
          create: vi.fn().mockResolvedValue({ status: 'COMPLETE', results: [] }),
          read: vi.fn().mockResolvedValue({ status: 'COMPLETE', results: [] }),
          update: vi.fn().mockResolvedValue({ status: 'COMPLETE', results: [] }),
        },
      },
      deals: {
        basicApi: {
          create: vi.fn().mockResolvedValue({
            id: '201',
            properties: { dealname: 'Test Deal', amount: '1000' },
          }),
          getById: vi.fn(),
          update: vi.fn(),
        },
      },
      companies: {
        basicApi: {
          create: vi.fn().mockResolvedValue({
            id: '301',
            properties: { name: 'Test Co', domain: 'test.com' },
          }),
        },
      },
    },
  };
}

// tests/contacts.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { createMockHubSpotClient } from './mocks/hubspot';

vi.mock('../src/hubspot/client', () => ({
  getHubSpotClient: vi.fn(),
}));

describe('Contact operations', () => {
  const mockClient = createMockHubSpotClient();

  beforeEach(() => {
    vi.mocked(getHubSpotClient).mockReturnValue(mockClient as any);
  });

  it('should create a contact with required properties', async () => {
    const result = await mockClient.crm.contacts.basicApi.create({
      properties: { firstname: 'Jane', lastname: 'Doe', email: 'jane@test.com' },
      associations: [],
    });
    expect(result.id).toBe('101');
    expect(result.properties.email).toBe('jane@test.com');
  });
});
```

### Step 5: Developer Test Account

```bash
# Create a free developer test account at:
# https://developers.hubspot.com/get-started

# Use test account token for integration tests
# .env.local
HUBSPOT_ACCESS_TOKEN=pat-na1-test-xxxx  # test account token
HUBSPOT_PORTAL_ID=12345678              # test portal ID
```

## Output

- Client singleton with reset capability for tests
- Mock factory covering contacts, deals, companies
- Unit tests running without API calls
- Integration tests using developer test account
- Hot-reload dev loop with `tsx watch`

## Error Handling

| Error | Cause | Solution |
|-------|-------|----------|
| `HUBSPOT_ACCESS_TOKEN is required` | Missing env var | Copy `.env.example` to `.env.local` |
| Mock type mismatch | SDK version change | Update mock factory to match SDK types |
| Test timeout | Real API call leaked | Verify mocks are wired correctly |
| `429` in integration tests | Rate limited on test account | Add delay between test runs |

## Examples

### Integration Test with Real API

```typescript
// tests/integration/contacts.integration.test.ts
import { describe, it, expect } from 'vitest';
import * as hubspot from '@hubspot/api-client';

const shouldRun = process.env.HUBSPOT_TEST === 'true';

describe.skipIf(!shouldRun)('HubSpot Integration', () => {
  const client = new hubspot.Client({
    accessToken: process.env.HUBSPOT_ACCESS_TOKEN!,
  });

  it('should create and archive a test contact', async () => {
    const contact = await client.crm.contacts.basicApi.create({
      properties: {
        firstname: 'Integration',
        lastname: `Test-${Date.now()}`,
        email: `test-${Date.now()}@example.com`,
      },
      associations: [],
    });
    expect(contact.id).toBeDefined();

    // Clean up
    await client.crm.contacts.basicApi.archive(contact.id);
  });
});
```

## Resources

- [HubSpot Developer Test Accounts](https://developers.hubspot.com/docs/guides/apps/developer-test-accounts)
- [Vitest Documentation](https://vitest.dev/)
- [@hubspot/api-client GitHub](https://github.com/HubSpot/hubspot-api-nodejs)

## Next Steps

See `hubspot-sdk-patterns` for production-ready code patterns.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in testing →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.