resources/boost/skills/services/SKILL.md
Orchestration classes that coordinate multiple Actions, external APIs, or domain operations into a cohesive workflow. Services own transaction boundaries and third-party API integrations.
npx skillsauth add codebar-ag/coding-guidelines servicesInstall 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.
app/Services/.PaymentService, SubscriptionService, StripeService.Manager or Handler.// Service split example
// Before: BillingService handles invoicing + payout + tax exports.
// After: InvoiceService, PayoutService, and TaxExportService with narrow APIs.
DB::transaction().processOrderPayment, refund).namespace App\Services;
use App\Actions\CreateInvoice;
use App\Actions\ChargePaymentMethod;
use App\Actions\SendPaymentConfirmation;
use App\Models\Order;
use App\Models\Payment;
use Illuminate\Support\Facades\DB;
class PaymentService
{
public function __construct(
private readonly CreateInvoice $createInvoice,
private readonly ChargePaymentMethod $chargePaymentMethod,
private readonly SendPaymentConfirmation $sendConfirmation,
) {}
public function processOrderPayment(Order $order): Payment
{
return DB::transaction(function () use ($order) {
$invoice = $this->createInvoice->execute($order);
$payment = $this->chargePaymentMethod->execute($order, $invoice);
$this->sendConfirmation->execute($payment);
return $payment;
});
}
public function refund(Payment $payment): void
{
// refund orchestration logic
}
}
// When NOT to use a Service: single operation belongs in an Action
class CreateInvoice
{
public function execute(int $orderId): Invoice
{
$order = Order::findOrFail($orderId);
return Invoice::create([
'order_id' => $order->id,
'status' => 'draft',
]);
}
}
// Registering an external service wrapper — AppServiceProvider
$this->app->singleton(StripeService::class, function () {
return new StripeService(config('services.stripe.secret'));
});
// Controller
class PaymentController extends Controller
{
public function store(StorePaymentRequest $request, PaymentService $service): JsonResponse
{
$order = Order::findOrFail($request->validated('order_id'));
$payment = $service->processOrderPayment($order);
return new JsonResponse(new PaymentResource($payment), 201);
}
}
// External integration retry + error mapping
public function capture(string $paymentIntentId): PaymentCaptureResult
{
try {
return retry(3, fn () => $this->stripe->capture($paymentIntentId), 200);
} catch (\Throwable $exception) {
throw new PaymentGatewayException(
message: 'Stripe capture failed.',
previous: $exception,
);
}
}
app/Services/ with a domain-specific name.DB::transaction().processOrderPayment, refund).DataManager, UserHandler, or other generic names instead of a domain-specific name.// Anti-pattern: direct SQL and HTTP coupling inside service
class UserService
{
public function syncUser(int $id): void
{
DB::statement("UPDATE users SET synced_at = NOW() WHERE id = {$id}");
file_get_contents('https://third-party.example/sync/' . $id);
}
}
Actions/SKILL.md — single-operation units that services composeSaloon/SKILL.md — preferred abstraction for external HTTP integrationstesting
Translation and localization conventions for Laravel. Use when adding user-facing strings, creating translation files, or working with lang/ directory.
tools
Reusable behaviour shared across multiple unrelated classes. Traits provide shared Eloquent scopes, accessors, lifecycle hooks, and small stateless helper methods.
development
Tailwind CSS v4 styling conventions. Use when working with CSS, Tailwind utilities, or customizing the theme in Laravel projects.
development
Saloon-based service layer pattern for all external API integrations. Every new external API integration must use Saloon — no raw HTTP calls.