> temporal-sdk
You are an expert in Temporal, the open-source durable execution platform for building reliable distributed applications. You help developers write workflows that survive process crashes, network failures, and deployments — with automatic retries, timeouts, cancellation, signals, queries, and versioning — replacing fragile state machines, manual retry logic, and error-prone queue-based orchestration with simple, testable code.
curl "https://skillshub.wtf/TerminalSkills/skills/temporal-sdk?format=md"Temporal — Durable Workflow Orchestration
You are an expert in Temporal, the open-source durable execution platform for building reliable distributed applications. You help developers write workflows that survive process crashes, network failures, and deployments — with automatic retries, timeouts, cancellation, signals, queries, and versioning — replacing fragile state machines, manual retry logic, and error-prone queue-based orchestration with simple, testable code.
Core Capabilities
Workflow and Activities
// src/workflows.ts — Durable workflow (survives crashes, restarts)
import { proxyActivities, sleep, condition, setHandler, defineSignal, defineQuery } from "@temporalio/workflow";
import type * as activities from "./activities";
const { chargePayment, shipOrder, sendEmail, refundPayment } = proxyActivities<typeof activities>({
startToCloseTimeout: "30s",
retry: { maximumAttempts: 3, initialInterval: "1s", backoffCoefficient: 2 },
});
// Signals and queries
const cancelSignal = defineSignal("cancel");
const statusQuery = defineQuery<string>("status");
export async function orderWorkflow(order: Order): Promise<OrderResult> {
let status = "processing";
let cancelled = false;
setHandler(cancelSignal, () => { cancelled = true; });
setHandler(statusQuery, () => status);
// Step 1: Charge payment
status = "charging";
const paymentId = await chargePayment(order.total, order.paymentMethod);
// Check for cancellation
if (cancelled) {
await refundPayment(paymentId);
return { status: "cancelled" };
}
// Step 2: Ship order (with saga compensation on failure)
status = "shipping";
try {
const tracking = await shipOrder(order.items, order.address);
status = "shipped";
// Step 3: Send confirmation
await sendEmail(order.email, "order-shipped", { tracking });
// Step 4: Wait for delivery (up to 14 days)
status = "in-transit";
const delivered = await condition(() => cancelled, "14 days");
if (!delivered) {
status = "delivered";
await sendEmail(order.email, "delivery-confirmed", {});
}
return { status: "completed", tracking, paymentId };
} catch (err) {
// Saga: compensate by refunding if shipping fails
status = "refunding";
await refundPayment(paymentId);
await sendEmail(order.email, "order-failed", { reason: "shipping failed" });
return { status: "failed", reason: "shipping_failed" };
}
}
// Scheduled workflow
export async function subscriptionWorkflow(userId: string): Promise<void> {
while (true) {
await chargeSubscription(userId);
await sleep("30 days"); // Durable sleep — survives server restarts
}
}
Activities
// src/activities.ts — Non-deterministic operations (API calls, DB writes)
export async function chargePayment(amount: number, method: PaymentMethod): Promise<string> {
const response = await stripe.paymentIntents.create({
amount: Math.round(amount * 100),
currency: "usd",
payment_method: method.id,
confirm: true,
});
return response.id;
}
export async function shipOrder(items: Item[], address: Address): Promise<string> {
const shipment = await shippingApi.createShipment({ items, destination: address });
return shipment.trackingNumber;
}
export async function sendEmail(to: string, template: string, data: any): Promise<void> {
await mailer.send({ to, template, data });
}
Worker and Client
// src/worker.ts
import { Worker } from "@temporalio/worker";
import * as activities from "./activities";
const worker = await Worker.create({
workflowsPath: require.resolve("./workflows"),
activities,
taskQueue: "orders",
});
await worker.run();
// src/client.ts — Start workflows
import { Client } from "@temporalio/client";
const client = new Client();
const handle = await client.workflow.start(orderWorkflow, {
taskQueue: "orders",
workflowId: `order-${orderId}`, // Idempotent by ID
args: [order],
});
// Query status
const status = await handle.query(statusQuery);
// Signal cancellation
await handle.signal(cancelSignal);
Installation
npm install @temporalio/client @temporalio/worker @temporalio/workflow @temporalio/activity
# Run Temporal server locally:
temporal server start-dev
Best Practices
- Workflows are deterministic — No I/O, randomness, or timestamps in workflows; use activities for side effects
- Activities for side effects — All API calls, DB writes, file I/O go in activities; retried independently
- Idempotent activities — Activities may retry; use idempotency keys for payments, API calls
- Workflow IDs for dedup — Use business IDs (
order-123) as workflow IDs; prevents duplicate processing - Saga pattern — Use try/catch for compensation; refund payment if shipping fails
- Signals for external input — Use signals for user actions (cancel, approve); workflows wait for signals
- Queries for status — Use queries to inspect workflow state without side effects; real-time status checks
- Versioning — Use
patched()for workflow code changes; running workflows continue with old logic
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> xero-accounting
Integrate with the Xero accounting API to sync invoices, expenses, bank transactions, and contacts — and generate financial reports like P&L and balance sheet. Use when: connecting apps to Xero, automating bookkeeping workflows, syncing accounting data, or pulling financial reports programmatically.
> windsurf-rules
Configure Windsurf AI coding assistant with .windsurfrules and workspace rules. Use when: customizing Windsurf for a project, setting AI coding standards, creating team-shared Windsurf configurations, or tuning Cascade AI behavior.