Skip to main content
attio-local-dev-loop Set up a fast local development loop for Attio integrations with
hot reload, mock server, and integration tests.
Trigger: "attio dev setup", "attio local development",
"attio dev environment", "develop with attio", "attio project setup".
الانتقال إلى التثبيت سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill attio-local-dev-loopيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المزيد من هذا المستودع Implement user sign-up and sign-in flows with Clerk.
Use when building authentication UI, customizing sign-in experience,
or implementing OAuth social login.
Trigger with phrases like "clerk sign-in", "clerk sign-up",
"clerk login flow", "clerk OAuth", "clerk social login".
Implement session management and middleware with Clerk.
Use when managing user sessions, configuring route protection,
or implementing token refresh and custom JWT templates.
Trigger with phrases like "clerk session", "clerk middleware",
"clerk route protection", "clerk token", "clerk JWT".
Configure enterprise SSO, role-based access control, and organization management.
Use when implementing SSO integration, configuring role-based permissions,
or setting up organization-level controls.
Trigger with phrases like "clerk SSO", "clerk RBAC",
"clerk enterprise", "clerk roles", "clerk permissions", "clerk organizations".
المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
name attio-local-dev-loop description Set up a fast local development loop for Attio integrations with
hot reload, mock server, and integration tests.
Trigger: "attio dev setup", "attio local development",
"attio dev environment", "develop with attio", "attio project setup".
allowed-tools Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Bash(npx:*), Grep version 1.6.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","crm","attio"] compatibility Designed for Claude Code
Attio Local Dev Loop
Overview Set up a fast, reproducible local development workflow for Attio REST API integrations. Includes project structure, typed client, mock server for offline work, and integration test harness.
Prerequisites
Completed attio-install-auth setup
Node.js 18+ with npm or pnpm
TypeScript 5+
Instructions
Step 1: Project Structure my-attio-integration/
├── src/
│ ├── attio/
│ │ ├── client.ts # Typed fetch wrapper (see attio-install-auth)
│ │ ├── types.ts # Attio response types
│ │ └── config.ts # Env-based configuration
│ ├── services/
│ │ ├── people.ts # People record operations
│ │ ├── companies.ts # Company record operations
│ │ └── lists.ts # List entry operations
│ └── index.ts
├── tests/
│ ├── mocks/
│ │ └── attio-fixtures.ts # Realistic API response fixtures
│ ├── unit/
│ │ └── people.test.ts
│ └── integration/
│ └── attio-live.test.ts # Runs against real API (CI only)
├── .env.example
├── .env.local # Git-ignored, real credentials
├── tsconfig.json
└── package.json
Step 2: Type the Attio Response Model
export interface AttioRecordId {
object_id : string ;
record_id : string ;
}
export interface AttioValue <T = unknown > {
active_from : string ;
active_until : string | null ;
created_by_actor : { type : string ; id : string };
attribute_type : string ;
[key : string ]: T | unknown ;
}
export interface AttioRecord {
id : AttioRecordId ;
created_at : string ;
values : Record <string , AttioValue []>;
}
export interface AttioListResponse <T> {
data : T[];
pagination ?: {
next_cursor ?: string ;
has_more ?: boolean ;
};
}
export interface AttioError {
status_code : number ;
type : string ;
code : string ;
message : string ;
}
Step 3: Environment Configuration
export interface AttioConfig {
apiKey : string ;
baseUrl : string ;
timeout : number ;
environment : "development" | "staging" | "production" ;
}
export function loadConfig ( ): AttioConfig {
const env = process.env .NODE_ENV || "development" ;
return {
apiKey : process.env .ATTIO_API_KEY || "" ,
baseUrl : process.env .ATTIO_BASE_URL || "https://api.attio.com/v2" ,
timeout : parseInt (process.env .ATTIO_TIMEOUT || "30000" , 10 ),
environment : env as AttioConfig ["environment" ],
};
}
Step 4: Package Scripts for Dev Loop {
"scripts" : {
"dev" : "tsx watch src/index.ts" ,
"test" : "vitest run" ,
"test:watch" : "vitest --watch" ,
"test:integration" : "ATTIO_LIVE=1 vitest run tests/integration/" ,
"typecheck" : "tsc --noEmit" ,
"lint" : "eslint src/ tests/"
} ,
"devDependencies" : {
"tsx" : "^4.0.0" ,
"vitest" : "^2.0.0" ,
"typescript" : "^5.5.0" ,
"msw" : "^2.0.0"
}
}
Step 5: Mock Attio API with MSW
import { http, HttpResponse } from "msw" ;
import { setupServer } from "msw/node" ;
const BASE = "https://api.attio.com/v2" ;
export const handlers = [
http.get (`${BASE} /objects` , () =>
HttpResponse .json ({
data : [
{ api_slug : "people" , singular_noun : "Person" , plural_noun : "People" },
{ api_slug : "companies" , singular_noun : "Company" , plural_noun : "Companies" },
],
})
),
http.post (`${BASE} /objects/people/records/query` , () =>
HttpResponse .json ({
data : [
{
id : { object_id : "obj_people" , record_id : "rec_abc123" },
created_at : "2025-01-15T10:00:00.000Z" ,
values : {
name : [{ first_name : "Ada" , last_name : "Lovelace" , full_name : "Ada Lovelace" }],
email_addresses : [{ email_address : "ada@example.com" }],
},
},
],
})
),
http.post (`${BASE} /objects/people/records` , async ({ request }) => {
const body = (await request.json ()) as Record <string , unknown >;
return HttpResponse .json ({
data : {
id : { object_id : "obj_people" , record_id : `rec_${Date .now()} ` },
created_at : new Date ().toISOString (),
values : (body as any ).data ?.values || {},
},
}, { status : 200 });
}),
];
export const mockServer = setupServer (...handlers);
Step 6: Write Tests Against Mocks
import { describe, it, expect, beforeAll, afterAll } from "vitest" ;
import { mockServer } from "../mocks/attio-fixtures" ;
import { attioFetch } from "../../src/attio/client" ;
beforeAll (() => mockServer.listen ());
afterAll (() => mockServer.close ());
describe ("People Service" , () => {
it ("queries people records" , async () => {
const res = await attioFetch<{ data : any [] }>({
method : "POST" ,
path : "/objects/people/records/query" ,
body : { limit : 10 },
});
expect (res.data ).toHaveLength (1 );
expect (res.data [0 ].values .name [0 ].full_name ).toBe ("Ada Lovelace" );
});
it ("creates a person" , async () => {
const res = await attioFetch<{ data : { id : { record_id : string } } }>({
method : "POST" ,
path : "/objects/people/records" ,
body : {
data : { values : { email_addresses : ["test@example.com" ] } },
},
});
expect (res.data .id .record_id ).toBeTruthy ();
});
});
Step 7: Integration Test (Live API)
import { describe, it, expect } from "vitest" ;
import { attioFetch } from "../../src/attio/client" ;
const LIVE = process.env .ATTIO_LIVE === "1" ;
describe.skipIf (!LIVE )("Attio Live API" , () => {
it ("lists objects from real workspace" , async () => {
const res = await attioFetch<{ data : Array <{ api_slug : string }> }>({
path : "/objects" ,
});
expect (res.data .map ((o ) => o.api_slug )).toContain ("people" );
});
});
Error Handling Issue Cause Solution fetch is not definedNode < 18 Upgrade Node.js or add undici MSW not intercepting Wrong base URL Match ATTIO_BASE_URL in mock handlers Integration test fails Missing/invalid token Set ATTIO_API_KEY in .env.local TypeScript errors on values Attio multiselect arrays Values are always arrays -- type as T[]
Resources
Next Steps See attio-sdk-patterns for production-ready client patterns.