.claude/skills/architecture/SKILL.md
Software architecture patterns and guidelines. Covers Clean Architecture, DDD, microservices, monoliths, and how to choose the right approach. Use when designing systems, refactoring, asking "how should I structure", "which architecture", "monolith vs microservices".
npx skillsauth add YaroslavKomarov/ShedulerBot ai-factory.architectureInstall 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.
Practical guidelines for software architecture decisions.
/ai-factory.architecture — Overview and decision guide/ai-factory.architecture clean — Clean Architecture/ai-factory.architecture ddd — Domain-Driven Design/ai-factory.architecture microservices — Microservices patterns/ai-factory.architecture monolith — Modular monolith/ai-factory.architecture layers — Layered architecture| Factor | Monolith | Modular Monolith | Microservices | |--------|----------|------------------|---------------| | Team size | 1-10 | 5-30 | 20+ | | Domain complexity | Low-Medium | Medium-High | High | | Scale requirements | Moderate | Moderate-High | Very High | | Deploy independence | ❌ | Partial | ✅ | | Initial velocity | ✅ Fast | ✅ Fast | ❌ Slow | | Operational complexity | ✅ Low | ✅ Low | ❌ High |
New project? → Start with Modular Monolith
↓
Growing team + clear domain boundaries? → Extract to Microservices
↓
Single team + unclear boundaries? → Stay Monolith, refine modules
Dependencies point inward. Inner layers know nothing about outer layers.
┌─────────────────────────────────────────────────────────┐
│ Frameworks & Drivers │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Interface Adapters │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Application Layer │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │ │
│ │ │ │ Domain Layer │ │ │ │
│ │ │ │ (Entities & Business Rules) │ │ │ │
│ │ │ └─────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
src/
├── domain/ # Core business logic (no dependencies)
│ ├── entities/
│ │ └── User.ts
│ ├── value-objects/
│ │ └── Email.ts
│ └── repositories/ # Interfaces only
│ └── IUserRepository.ts
│
├── application/ # Use cases (depends on domain)
│ ├── use-cases/
│ │ ├── CreateUser.ts
│ │ └── GetUserById.ts
│ └── services/
│ └── AuthService.ts
│
├── infrastructure/ # External concerns (implements interfaces)
│ ├── database/
│ │ └── PrismaUserRepository.ts
│ ├── external/
│ │ └── StripePaymentGateway.ts
│ └── config/
│
└── presentation/ # UI/API layer
├── api/
│ └── routes/
├── controllers/
└── dto/
// ✅ domain/repositories/IUserRepository.ts (interface)
interface IUserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<void>;
}
// ✅ infrastructure/database/PrismaUserRepository.ts (implementation)
class PrismaUserRepository implements IUserRepository {
constructor(private prisma: PrismaClient) {}
async findById(id: string): Promise<User | null> {
const data = await this.prisma.user.findUnique({ where: { id } });
return data ? User.fromPersistence(data) : null;
}
}
// ✅ application/use-cases/GetUserById.ts (depends on interface)
class GetUserById {
constructor(private userRepo: IUserRepository) {}
async execute(id: string): Promise<User> {
const user = await this.userRepo.findById(id);
if (!user) throw new UserNotFoundError(id);
return user;
}
}
Bounded Contexts: Explicit boundaries around domain models
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Ordering │ │ Inventory │ │ Shipping │
│ Context │────▶│ Context │────▶│ Context │
│ │ │ │ │ │
│ Order │ │ Product │ │ Shipment │
│ OrderLine │ │ Stock │ │ Carrier │
│ Customer │ │ Warehouse │ │ TrackingInfo │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Context Mapping: How contexts communicate
Entities: Identity-based objects
class Order {
constructor(
public readonly id: OrderId,
private items: OrderItem[],
private status: OrderStatus
) {}
addItem(product: Product, quantity: number): void {
if (this.status !== 'draft') {
throw new Error('Cannot modify confirmed order');
}
this.items.push(new OrderItem(product, quantity));
}
}
Value Objects: Immutable, equality by value
class Money {
constructor(
public readonly amount: number,
public readonly currency: string
) {
if (amount < 0) throw new Error('Amount cannot be negative');
}
add(other: Money): Money {
if (this.currency !== other.currency) {
throw new Error('Currency mismatch');
}
return new Money(this.amount + other.amount, this.currency);
}
equals(other: Money): boolean {
return this.amount === other.amount && this.currency === other.currency;
}
}
Aggregates: Consistency boundaries
// Order is the Aggregate Root
// OrderItems can only be modified through Order
class Order {
private items: OrderItem[] = [];
// All invariants enforced here
addItem(item: OrderItem): void {
if (this.items.length >= 100) {
throw new Error('Order cannot have more than 100 items');
}
this.items.push(item);
}
}
Domain Events: Communicate state changes
class OrderPlaced implements DomainEvent {
constructor(
public readonly orderId: string,
public readonly customerId: string,
public readonly occurredAt: Date = new Date()
) {}
}
// Usage
order.place();
eventBus.publish(new OrderPlaced(order.id, order.customerId));
✅ Good boundaries:
- User Service (authentication, profiles)
- Order Service (order lifecycle)
- Payment Service (transactions, refunds)
- Notification Service (email, SMS, push)
❌ Bad boundaries:
- Database Service (too technical)
- Validation Service (too generic)
- Utils Service (not a domain)
Synchronous (HTTP/gRPC)
Order Service ──HTTP──▶ Inventory Service
"Check stock for product X"
Use for: Queries, real-time validation
Asynchronous (Events/Messages)
Order Service ──Event──▶ Message Broker ──▶ Notification Service
"OrderPlaced" (sends email)
Use for: Side effects, eventual consistency
Database per Service
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Orders │ │ Inventory │ │ Payments │
│ Service │ │ Service │ │ Service │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│ PostgreSQL │ MongoDB │ │ PostgreSQL
└───────┘ └───────┘ └───────┘
Saga Pattern for distributed transactions
Order Saga:
1. Create Order (Orders Service)
2. Reserve Inventory (Inventory Service)
3. Process Payment (Payment Service)
4. Confirm Order (Orders Service)
If step fails → Compensate previous steps
src/
├── modules/
│ ├── users/
│ │ ├── api/ # HTTP handlers
│ │ ├── domain/ # Business logic
│ │ ├── infra/ # Database, external
│ │ └── index.ts # Public API only
│ │
│ ├── orders/
│ │ ├── api/
│ │ ├── domain/
│ │ ├── infra/
│ │ └── index.ts
│ │
│ └── payments/
│ └── ...
│
├── shared/ # Truly shared code
│ ├── kernel/ # Base classes, interfaces
│ └── utils/ # Pure utilities
│
└── main.ts # Composition root
// ✅ Good: Module exposes explicit public API
// modules/users/index.ts
export { UserService } from './domain/UserService';
export { User } from './domain/User';
export type { CreateUserDTO } from './api/dto';
// ✅ Good: Other modules use public API
import { UserService } from '@/modules/users';
// ❌ Bad: Reaching into module internals
import { UserRepository } from '@/modules/users/infra/UserRepository';
Q: New greenfield project?
A: Start with Modular Monolith
Q: Existing messy codebase?
A: Apply Clean Architecture gradually
Q: Team > 50 engineers?
A: Consider Microservices with clear domain boundaries
Q: Need to scale one component independently?
A: Extract that component as a service
Q: Unclear requirements?
A: Keep it simple, refactor when patterns emerge
development
Verify completed implementation against the plan. Checks that all tasks were fully implemented, nothing was forgotten, code compiles, tests pass, and quality standards are met. Use after "/ai-factory.implement" completes, or when user says "verify", "check work", "did we miss anything".
data-ai
Create a step-by-step implementation plan for a feature or task. Breaks down work into actionable tasks tracked via the task system. Use when user says "plan", "create tasks", "break down", or "make a plan for".
tools
# Supabase TypeScript Patterns Patterns for using Supabase with TypeScript in this project. Uses **service role key** (server-side only). Tables are prefixed `sch_`. ## Client Setup ```typescript // src/db/client.ts import { createClient } from "@supabase/supabase-js"; import type { Database } from "./types"; // generated types export const supabase = createClient<Database>( process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!, // server-side only, bypasses RLS { auth:
development
Generate professional Agent Skills for Claude Code and other AI agents. Creates complete skill packages with SKILL.md, references, scripts, and templates. Use when creating new skills, generating custom slash commands, or building reusable AI capabilities. Validates against Agent Skills specification.