Agent skill
treido-backend
Build and modify Treido server-side logic including Server Actions, API routes, Stripe integration, and caching. Use when working on app/actions/, app/api/, lib/ directories, webhooks, payment flows, or any server-side data fetching. Triggers include creating actions, API endpoints, Stripe checkout/webhooks, or fixing caching issues.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/treido-backend
SKILL.md
Treido Backend
Deprecated (2026-01-29). Use
treido-orchestrator+treido-impl-backend(andtreido-audit-*+treido-verify).
Quick Start
- Identify the entrypoint (action, route handler, or webhook)
- Define the contract (input/output types, auth requirements, error cases)
- Implement (1-3 files max per batch)
- Run verification:
pnpm -s typecheck && pnpm -s lint
Decision Tree
What are you building?
├─ Server Action → app/actions/ (shared) or app/[locale]/(group)/**/_actions/ (route-private)
├─ API Route → app/api/**/route.ts
├─ Stripe webhook → app/api/webhooks/stripe/route.ts
├─ Utility function → lib/
└─ UI component → Wrong skill. Use treido-frontend
File Boundaries
| Type | Location | Rule |
|---|---|---|
| Shared actions | app/actions/ |
Used across multiple routes |
| Route-private actions | app/[locale]/(group)/**/_actions/ |
Single route only |
| API routes | app/api/ |
REST endpoints, webhooks |
| Utilities | lib/ |
Pure functions, no React |
Server Actions
Basic Pattern
// app/actions/cart.ts
'use server';
import { revalidateTag } from 'next/cache';
import { createClient } from '@/lib/supabase/server';
export async function addToCart(productId: string, quantity: number) {
// 1. Validate input
if (!productId || quantity < 1) {
throw new Error('Invalid input');
}
// 2. Get authenticated client
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
throw new Error('Unauthorized');
}
// 3. Perform operation
const { error } = await supabase
.from('cart_items')
.insert({ user_id: user.id, product_id: productId, quantity });
if (error) throw error;
// 4. Invalidate cache
revalidateTag('cart');
}
API Routes
Basic Pattern
// app/api/products/route.ts
import { NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
export async function GET(request: Request) {
const supabase = await createClient();
const { data, error } = await supabase
.from('products')
.select('id, title, price, images')
.eq('status', 'active')
.limit(20);
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(data);
}
Security Rules (Non-Negotiable)
No Secrets in Logs
// ❌ FORBIDDEN - leaks sensitive data
console.log('User data:', user);
console.log('Headers:', request.headers);
console.log('Token:', session.access_token);
// ✅ CORRECT - safe logging
console.log('Processing request for user:', user.id);
console.log('Action completed');
Supabase Query Projections
// ❌ FORBIDDEN in hot paths
const { data } = await supabase.from('products').select('*');
// ✅ CORRECT - explicit field projection
const { data } = await supabase
.from('products')
.select('id, title, price, images');
Stripe Integration
Checkout Session
// app/actions/checkout.ts
'use server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function createCheckoutSession(items: CartItem[]) {
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: items.map(item => ({
price_data: {
currency: 'bgn',
product_data: { name: item.title },
unit_amount: item.price * 100, // cents
},
quantity: item.quantity,
})),
success_url: `${process.env.NEXT_PUBLIC_APP_URL}/checkout/success`,
cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/checkout/cancel`,
});
return session.url;
}
Webhook Handler
// app/api/webhooks/stripe/route.ts
import Stripe from 'stripe';
import { headers } from 'next/headers';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(request: Request) {
const body = await request.text();
const headersList = await headers();
const signature = headersList.get('stripe-signature')!;
// 1. Verify signature
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err) {
return new Response('Invalid signature', { status: 400 });
}
// 2. Handle event (idempotently)
switch (event.type) {
case 'checkout.session.completed':
await handleCheckoutComplete(event.data.object);
break;
// Add other event types
}
return new Response('OK');
}
Caching Rules
With 'use cache'
'use cache';
import { cacheLife, cacheTag } from 'next/cache';
export async function getProducts() {
cacheLife('hours');
cacheTag('products');
const supabase = await createClient();
const { data } = await supabase
.from('products')
.select('id, title, price');
return data;
}
⚠️ FORBIDDEN in Cached Functions
'use cache';
// ❌ NEVER call these inside cached functions
import { cookies, headers } from 'next/headers';
await cookies(); // FORBIDDEN
await headers(); // FORBIDDEN
Verification
After every change:
pnpm -s typecheck && pnpm -s lint
For payment/auth flows:
REUSE_EXISTING_SERVER=true pnpm -s test:e2e:smoke
References
For caching patterns: See references/caching.md For Stripe patterns: See references/stripe.md
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?