skills/aayushbaniya2006/credits-handler/SKILL.md
Manage the credit system (allocation, purchasing, usage). Use when adding credit types, configuring pricing, or building credit UI.
npx skillsauth add aiskillstore/marketplace credits-handlerInstall 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.
This skill guides you through the entire credit system, from backend configuration to frontend UI implementation.
All credit configuration lives in src/lib/credits/config.ts.
Define the Type: Add the new type to creditTypeSchema enum.
export const creditTypeSchema = z.enum([
"image_generation",
"video_generation",
"your_new_credit_type" // Add this
]);
Configure Pricing & Metadata: Add an entry to creditsConfig.
your_new_credit_type: {
name: "New Credit Name",
currency: "USD",
minimumAmount: 10,
// Option A: Fixed Slabs
slabs: [
{ from: 1, to: 100, pricePerUnit: 0.10 },
{ from: 101, to: 1000, pricePerUnit: 0.08 },
],
// Option B: Dynamic Calculator (e.g., based on user plan)
priceCalculator: (amount, userPlan) => {
// Logic here
return amount * 0.1;
}
}
Plan Allocations (Optional): Define how many credits are given when subscribing to a plan in onPlanChangeCredits.
To let users purchase credits, use the useBuyCredits hook. This hook handles price calculation (factoring in plan discounts) and generating checkout URLs.
useBuyCreditsLocation: src/lib/credits/useBuyCredits.ts
import useBuyCredits from "@/lib/credits/useBuyCredits";
import { PlanProvider } from "@/lib/plans/getSubscribeUrl";
const {
price, // Calculated total price (number | undefined)
isLoading, // Price calculation in progress
error, // Error state
getBuyCreditsUrl // Function to generate payment URL
} = useBuyCredits(creditType, amount);
Here is a pattern for creating a credit purchase UI, similar to src/components/website/website-credits-section.tsx.
"use client";
import { useState } from "react";
import useBuyCredits from "@/lib/credits/useBuyCredits";
import { PlanProvider } from "@/lib/plans/getSubscribeUrl";
import { Button } from "@/components/ui/button";
import { Loader2 } from "lucide-react";
// 1. Define your packages
const PACKAGE = {
credits: 100,
name: "Starter Pack",
};
export function BuyCreditsCard({ creditType }: { creditType: "image_generation" }) {
const [provider] = useState(PlanProvider.STRIPE); // or LEMONSQUEEZY
// 2. Call the hook
const { price, isLoading, error, getBuyCreditsUrl } = useBuyCredits(
creditType,
PACKAGE.credits
);
// 3. Handle Purchase
const handleBuy = () => {
const url = getBuyCreditsUrl(provider);
window.location.href = url;
};
// 4. Render UI
return (
<div className="border p-4 rounded-lg">
<h3>{PACKAGE.name}</h3>
<div className="text-2xl font-bold">
{isLoading ? (
<Loader2 className="animate-spin" />
) : (
`$${price?.toFixed(2) || "0.00"}`
)}
</div>
<Button
onClick={handleBuy}
disabled={isLoading || !price}
className="w-full mt-4"
>
Buy {PACKAGE.credits} Credits
</Button>
{error && <p className="text-red-500 text-sm">{error.message}</p>}
</div>
);
}
To show the user's current balance, use the useCredits hook.
useCreditsLocation: src/lib/users/useCredits.ts
const {
credits, // Record<string, number> | undefined
// e.g. { "image_generation": 100, "video_generation": 50 }
isLoading, // boolean
error, // any
mutate // SWR mutate function to refresh data
} = useCredits();
import useCredits from "@/lib/users/useCredits";
export function CreditBalance() {
const { credits, isLoading } = useCredits();
if (isLoading) return <div>Loading...</div>;
return (
<div>
Image Credits: {credits?.image_generation || 0}
</div>
);
}
These functions are used in API routes and webhooks.
Use allocatePlanCredits to give users credits when they subscribe/upgrade.
src/lib/credits/allocatePlanCredits.tsuserId, planId, paymentId (for idempotency).onPlanChangeCredits config and adds credits if applicable.To manually manipulate balances, use helpers from src/lib/credits/recalculate.ts (e.g., addCredits, deductCredits).
Note: Always ensure you have a unique paymentId or transaction reference when adding credits to prevent duplicates.
Use canDeductCredits before performing an action.
import { canDeductCredits } from "@/lib/credits/credits";
// Check if user has enough credits
const hasBalance = canDeductCredits(
"image_generation",
1,
user // Must contain { credits: { ... } }
);
if (!hasBalance) {
throw new Error("Insufficient credits");
}
For deep dives into database schema and architecture, see reference.md.
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.