Agent skill
klaviyo-local-dev-loop
Configure Klaviyo local development with hot reload, mocking, and testing. Use when setting up a development environment, configuring test workflows, or establishing a fast iteration cycle with the Klaviyo API. Trigger with phrases like "klaviyo dev setup", "klaviyo local development", "klaviyo dev environment", "develop with klaviyo", "klaviyo testing".
Install this agent skill to your Project
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/main/plugins/saas-packs/klaviyo-pack/skills/klaviyo-local-dev-loop
SKILL.md
Klaviyo Local Dev Loop
Overview
Set up a fast, reproducible local development workflow for Klaviyo integrations with hot reload, SDK mocking, and integration tests.
Prerequisites
- Completed
klaviyo-install-authsetup - Node.js 18+ with npm/pnpm
klaviyo-apipackage installed
Instructions
Step 1: Project Structure
my-klaviyo-project/
├── src/
│ ├── klaviyo/
│ │ ├── client.ts # ApiKeySession + API class singletons
│ │ ├── profiles.ts # Profile operations
│ │ ├── events.ts # Event tracking
│ │ └── lists.ts # List management
│ └── index.ts
├── tests/
│ ├── unit/
│ │ └── profiles.test.ts # Mocked SDK tests
│ └── integration/
│ └── klaviyo.test.ts # Live API tests (CI only)
├── .env.local # Local secrets (git-ignored)
├── .env.example # Template for team
├── .env.test # Test environment (sandbox key)
└── package.json
Step 2: Environment Configuration
# .env.example (commit this)
KLAVIYO_PRIVATE_KEY=pk_your_test_key_here
KLAVIYO_PUBLIC_KEY=YourPublicKey
NODE_ENV=development
# .env.local (git-ignored, actual secrets)
KLAVIYO_PRIVATE_KEY=pk_********************************
// package.json scripts
{
"scripts": {
"dev": "tsx watch src/index.ts",
"test": "vitest",
"test:watch": "vitest --watch",
"test:integration": "KLAVIYO_TEST=1 vitest --config vitest.integration.config.ts",
"typecheck": "tsc --noEmit"
}
}
Step 3: SDK Client Singleton
// src/klaviyo/client.ts
import {
ApiKeySession,
ProfilesApi,
EventsApi,
ListsApi,
SegmentsApi,
CampaignsApi,
MetricsApi,
} from 'klaviyo-api';
let session: ApiKeySession | null = null;
function getSession(): ApiKeySession {
if (!session) {
const key = process.env.KLAVIYO_PRIVATE_KEY;
if (!key) throw new Error('KLAVIYO_PRIVATE_KEY not set');
session = new ApiKeySession(key);
}
return session;
}
// Lazy singletons -- only instantiate what you use
export const profiles = () => new ProfilesApi(getSession());
export const events = () => new EventsApi(getSession());
export const lists = () => new ListsApi(getSession());
export const segments = () => new SegmentsApi(getSession());
export const campaigns = () => new CampaignsApi(getSession());
export const metrics = () => new MetricsApi(getSession());
Step 4: Unit Testing with Mocks
// tests/unit/profiles.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
// Mock the entire klaviyo-api module
vi.mock('klaviyo-api', () => ({
ApiKeySession: vi.fn(),
ProfilesApi: vi.fn().mockImplementation(() => ({
createProfile: vi.fn().mockResolvedValue({
body: {
data: {
id: '01JMOCKPROFILEID',
type: 'profile',
attributes: { email: 'test@example.com', firstName: 'Test' },
},
},
}),
getProfiles: vi.fn().mockResolvedValue({
body: {
data: [{ id: '01JMOCKPROFILEID', attributes: { email: 'test@example.com' } }],
links: { next: null },
},
}),
})),
ProfileEnum: { Profile: 'profile' },
}));
import { ProfilesApi, ApiKeySession } from 'klaviyo-api';
describe('Profile operations', () => {
let profilesApi: ProfilesApi;
beforeEach(() => {
const session = new ApiKeySession('pk_test_key');
profilesApi = new ProfilesApi(session);
});
it('creates a profile with email', async () => {
const result = await profilesApi.createProfile({
data: {
type: 'profile' as any,
attributes: { email: 'test@example.com', firstName: 'Test' },
},
});
expect(result.body.data.id).toBe('01JMOCKPROFILEID');
});
});
Step 5: Integration Test (runs against live API)
// tests/integration/klaviyo.test.ts
import { describe, it, expect } from 'vitest';
import { ApiKeySession, ProfilesApi, AccountsApi } from 'klaviyo-api';
const SKIP = !process.env.KLAVIYO_TEST;
describe.skipIf(SKIP)('Klaviyo Integration', () => {
const session = new ApiKeySession(process.env.KLAVIYO_PRIVATE_KEY!);
it('connects to Klaviyo account', async () => {
const accountsApi = new AccountsApi(session);
const result = await accountsApi.getAccounts();
expect(result.body.data).toHaveLength(1);
expect(result.body.data[0].id).toBeTruthy();
});
it('creates and retrieves a test profile', async () => {
const profilesApi = new ProfilesApi(session);
const testEmail = `test-${Date.now()}@example.com`;
await profilesApi.createProfile({
data: {
type: 'profile' as any,
attributes: { email: testEmail, firstName: 'IntegrationTest' },
},
});
const profiles = await profilesApi.getProfiles({
filter: `equals(email,"${testEmail}")`,
});
expect(profiles.body.data[0].attributes.firstName).toBe('IntegrationTest');
});
});
Step 6: Hot Reload Development
# Start dev server with file watching
npm run dev
# In another terminal, run tests on change
npm run test:watch
Output
- Working dev environment with hot reload via
tsx watch - Unit tests with mocked
klaviyo-apiSDK - Integration tests gated behind
KLAVIYO_TEST=1 - Client singleton pattern for consistent SDK usage
Error Handling
| Error | Cause | Solution |
|---|---|---|
KLAVIYO_PRIVATE_KEY not set |
Missing .env.local | Copy from .env.example |
| Mock type errors | SDK type mismatches | Use as any for mock enum values |
| Integration test 429 | Rate limited in CI | Add delays between tests or use test key |
tsx not found |
Missing dependency | npm install -D tsx |
Resources
Next Steps
See klaviyo-sdk-patterns for production-ready code patterns.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
dockerfile-generator
Dockerfile Generator - Auto-activating skill for DevOps Basics. Triggers on: dockerfile generator, dockerfile generator Part of the DevOps Basics skill category.
branch-naming-helper
Branch Naming Helper - Auto-activating skill for DevOps Basics. Triggers on: branch naming helper, branch naming helper Part of the DevOps Basics skill category.
readme-generator
Readme Generator - Auto-activating skill for DevOps Basics. Triggers on: readme generator, readme generator Part of the DevOps Basics skill category.
makefile-generator
Makefile Generator - Auto-activating skill for DevOps Basics. Triggers on: makefile generator, makefile generator Part of the DevOps Basics skill category.
gitignore-generator
Gitignore Generator - Auto-activating skill for DevOps Basics. Triggers on: gitignore generator, gitignore generator Part of the DevOps Basics skill category.
pre-commit-hook-setup
Pre Commit Hook Setup - Auto-activating skill for DevOps Basics. Triggers on: pre commit hook setup, pre commit hook setup Part of the DevOps Basics skill category.
Didn't find tool you were looking for?