.claude/skills/dapr-integration/SKILL.md
Integrate Dapr building blocks for event-driven microservices - Pub/Sub, State Management, Secrets, Service Invocation, and Jobs API. Use when implementing event-driven architecture for Phase 5. (project)
npx skillsauth add maneeshanif/todo-spec-driven dapr-integrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
constitution-prompt-phase-5.mddapr --versiondapr init or dapr init -k for Kubernetesdapr-components/ directorydapr run commands| Building Block | Purpose | Phase 5 Usage | |----------------|---------|---------------| | Pub/Sub | Event messaging | Task events, reminders, audit logs | | State | Key-value storage | Cache, session state | | Secrets | Secret management | API keys, DB credentials | | Service Invocation | Service-to-service calls | Microservice communication | | Jobs API | Scheduled tasks | Recurring task scheduling |
Create dapr-components/pubsub.yaml:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: taskpubsub
namespace: todo-app
spec:
type: pubsub.kafka
version: v1
metadata:
- name: brokers
value: "kafka:9092"
- name: consumerGroup
value: "todo-consumer-group"
- name: authType
value: "none"
- name: disableTls
value: "true"
scopes:
- backend
- notification-service
- recurring-service
- audit-service
Create dapr-components/statestore.yaml:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
namespace: todo-app
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: "redis:6379"
- name: redisPassword
value: ""
- name: actorStateStore
value: "true"
scopes:
- backend
Create dapr-components/secrets.yaml:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: kubernetes-secrets
namespace: todo-app
spec:
type: secretstores.kubernetes
version: v1
metadata: []
uv add dapr dapr-ext-fastapi
from dapr.clients import DaprClient
async def publish_task_event(event_type: str, task_data: dict):
"""Publish task event to Kafka via Dapr."""
with DaprClient() as client:
client.publish_event(
pubsub_name="taskpubsub",
topic_name="task-events",
data=json.dumps({
"event_type": event_type,
"task": task_data,
"timestamp": datetime.utcnow().isoformat()
}),
data_content_type="application/json"
)
from dapr.ext.fastapi import DaprApp
from fastapi import FastAPI
app = FastAPI()
dapr_app = DaprApp(app)
@dapr_app.subscribe(pubsub="taskpubsub", topic="task-events")
async def handle_task_event(event: dict):
"""Handle incoming task events."""
event_type = event.get("event_type")
task_data = event.get("task")
if event_type == "task.created":
await process_new_task(task_data)
elif event_type == "task.completed":
await process_completed_task(task_data)
from dapr.clients import DaprClient
async def save_state(key: str, value: dict):
"""Save state to Dapr state store."""
with DaprClient() as client:
client.save_state(
store_name="statestore",
key=key,
value=json.dumps(value)
)
async def get_state(key: str) -> dict | None:
"""Get state from Dapr state store."""
with DaprClient() as client:
state = client.get_state(store_name="statestore", key=key)
return json.loads(state.data) if state.data else None
from dapr.clients import DaprClient
async def invoke_notification_service(user_id: str, message: str):
"""Invoke notification service via Dapr."""
with DaprClient() as client:
response = client.invoke_method(
app_id="notification-service",
method_name="send",
data=json.dumps({
"user_id": user_id,
"message": message
}),
http_verb="POST"
)
return response.json()
from dapr.clients import DaprClient
async def schedule_reminder(reminder_id: str, due_at: datetime):
"""Schedule a reminder using Dapr Jobs API."""
with DaprClient() as client:
# Create a scheduled job
client.start_workflow(
workflow_component="dapr",
workflow_name="reminder-workflow",
input={
"reminder_id": reminder_id,
"scheduled_time": due_at.isoformat()
}
)
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
template:
metadata:
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "backend"
dapr.io/app-port: "8000"
dapr.io/enable-api-logging: "true"
dapr.io/log-level: "info"
dapr.io/config: "dapr-config"
spec:
containers:
- name: backend
image: evolution-todo/backend:latest
# Run backend with Dapr
dapr run --app-id backend \
--app-port 8000 \
--dapr-http-port 3500 \
--components-path ./dapr-components \
-- uv run uvicorn src.main:app --host 0.0.0.0 --port 8000
# Run notification service with Dapr
dapr run --app-id notification-service \
--app-port 8002 \
--dapr-http-port 3502 \
--components-path ./dapr-components \
-- uv run uvicorn services.notification.main:app --host 0.0.0.0 --port 8002
# Publish test event
dapr publish --publish-app-id backend \
--pubsub taskpubsub \
--topic task-events \
--data '{"event_type":"task.created","task":{"id":"123","title":"Test"}}'
dapr --version)dapr init or dapr init -k)dapr-components/dapr, dapr-ext-fastapi)| Topic | Publisher | Subscribers | Purpose |
|-------|-----------|-------------|---------|
| task-events | Backend | Notification, Audit, WebSocket | Task CRUD events |
| reminder-events | Recurring Service | Notification, Backend | Reminder triggers |
| audit-events | All Services | Audit Service | Audit logging |
| Issue | Cause | Solution |
|-------|-------|----------|
| Sidecar not starting | Missing annotations | Add dapr.io/enabled: "true" |
| Pub/Sub not working | Component not loaded | Check component scope |
| Connection refused | Wrong port | Verify app-port matches app |
| State not persisting | Redis not running | Start Redis container |
tools
Implement WebSocket service for real-time task synchronization across clients. Use when building real-time updates for Phase 5. (project)
data-ai
Implement Urdu language support with RTL layout, translations, and AI responses in Urdu. Bonus feature (+100 points) for Phase 5. (project)
development
DEPRECATED - Use chatkit-backend skill instead. SSE streaming is now part of the chatkit-backend skill for ChatKit integration.
development
Install and configure Shadcn/ui component library with Radix UI primitives, Aceternity UI effects, set up components, and manage the component registry. Use when adding Shadcn/ui to a Next.js project or installing specific UI components for Phase 2.