modular-architecture
Module organization patterns including ports and adapters (hexagonal), module communication, and data isolation. Use when structuring modular monoliths, defining module boundaries, setting up inter-module communication, or isolating database contexts. Includes MediatR patterns for internal events.
What this skill does
# Modular Architecture
## When to Use This Skill
Use this skill when you need to:
- Structure a modular monolith application
- Define boundaries between modules (bounded contexts)
- Set up inter-module communication patterns
- Implement ports and adapters (hexagonal) architecture
- Isolate database contexts between modules
- Configure MediatR for internal domain events
**Keywords:** modular monolith, modules, bounded contexts, ports and adapters, hexagonal architecture, module communication, data isolation, separate DbContext, MediatR, domain events, internal events, module boundaries
## Module Structure Pattern
### Core Principle
Organize code by **modules (business capabilities)**, not layers. Each module is a self-contained vertical slice with its own:
- Domain entities and value objects
- Application services and handlers
- Infrastructure implementations
- Data transfer objects for external communication
### Standard Module Layout
```text
src/
├── Modules/
│ ├── Ordering/
│ │ ├── Ordering.Core/ # Domain + Application
│ │ │ ├── Domain/ # Entities, Value Objects, Events
│ │ │ ├── Application/ # Commands, Queries, Handlers
│ │ │ └── Ports/ # Interfaces (driven/driving)
│ │ ├── Ordering.Infrastructure/ # External dependencies
│ │ │ ├── Persistence/ # EF Core, DbContext
│ │ │ └── Adapters/ # External service implementations
│ │ └── Ordering.DataTransfer/ # DTOs for module-to-module communication
│ ├── Inventory/
│ │ ├── Inventory.Core/
│ │ ├── Inventory.Infrastructure/
│ │ └── Inventory.DataTransfer/
│ └── Shared/ # Truly shared kernel (minimal)
│ └── Shared.Kernel/ # Common value objects, interfaces
└── Host/ # Composition root, startup
└── Api/ # Controllers, middleware
```
### Key Principles
1. **No cross-module domain references** - Modules cannot reference each other's Core projects
2. **DataTransfer for communication** - Use DTOs to pass data between modules
3. **Infrastructure stays internal** - Each module owns its persistence
4. **Minimal shared kernel** - Only truly universal concepts go in Shared
## Ports and Adapters (Hexagonal) Pattern
The hexagonal architecture separates business logic from external concerns through ports (interfaces) and adapters (implementations).
**Detailed guide:** See `references/ports-adapters-guide.md`
### Quick Reference
```text
┌─────────────────────────────────────────────────────────────┐
│ DRIVING SIDE (Primary) │
│ Controllers, CLI, Message Handlers, Tests │
│ │ │
│ ┌──────▼──────┐ │
│ │ PORTS │ (Input interfaces) │
│ │ IOrderService│ │
│ └──────┬──────┘ │
│ │ │
│ ┌────────────▼────────────┐ │
│ │ APPLICATION │ │
│ │ (Use Cases/Handlers) │ │
│ └────────────┬────────────┘ │
│ │ │
│ ┌────────────▼────────────┐ │
│ │ DOMAIN │ │
│ │ (Entities, Value Objs) │ │
│ └────────────┬────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ PORTS │ (Output interfaces) │
│ │IOrderRepository│ │
│ └──────┬──────┘ │
│ │ │
│ DRIVEN SIDE (Secondary) │
│ Databases, External APIs, File Systems, Queues │
└─────────────────────────────────────────────────────────────┘
```
**Driving Ports:** Interfaces the application exposes (implemented by the application)
**Driven Ports:** Interfaces the application needs (implemented by adapters)
## Module Communication
Modules must communicate without creating tight coupling. Two primary patterns:
**Detailed guide:** See `references/module-communication.md`
### Synchronous Communication (DataTransfer)
For query operations where immediate response is needed:
```csharp
// In Inventory module - needs to check product availability
public class CheckStockHandler
{
private readonly IOrderingModuleApi _orderingApi;
public async Task<StockStatus> Handle(CheckStockQuery query)
{
// Get order info through DataTransfer DTO
var orderDto = await _orderingApi.GetOrderSummary(query.OrderId);
// orderDto is from Ordering.DataTransfer project
}
}
```
### Asynchronous Communication (MediatR Domain Events)
For state changes that other modules need to react to:
```csharp
// In Ordering module - publishes event after order is placed
public class PlaceOrderHandler
{
private readonly IMediator _mediator;
public async Task Handle(PlaceOrderCommand command)
{
// ... create order ...
// Publish integration event (handled by other modules)
await _mediator.Publish(new OrderPlacedIntegrationEvent(
order.Id, order.Items.Select(i => i.ProductId)));
}
}
// In Inventory module - handles the event
public class OrderPlacedHandler : INotificationHandler<OrderPlacedIntegrationEvent>
{
public async Task Handle(OrderPlacedIntegrationEvent notification, CancellationToken ct)
{
// Reserve inventory for the order
await _inventoryService.ReserveStock(notification.ProductIds);
}
}
```
## Data Isolation Patterns
Each module should own its data to prevent tight coupling at the database level.
**Detailed guide:** See `references/data-patterns.md`
### Separate DbContext Per Module
```csharp
// Ordering module's DbContext
public class OrderingDbContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
// Only configure Ordering entities
builder.ApplyConfigurationsFromAssembly(typeof(OrderingDbContext).Assembly);
}
}
// Inventory module's DbContext
public class InventoryDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<StockLevel> StockLevels { get; set; }
}
```
### Key Rules
1. **No foreign keys between modules** - Use IDs as value objects instead
2. **No shared tables** - Each module owns its tables completely
3. **Same database is acceptable** - Separate schema/prefix per module
4. **Eventual consistency** - Accept that cross-module data may be stale
## MediatR Integration
MediatR provides the messaging infrastructure for both in-module CQRS and cross-module integration events.
**Detailed guide:** See `references/mediatr-integration.md`
### Registration Pattern
```csharp
// In each module's registration
public static class OrderingModule
{
public static IServiceCollection AddOrderingModule(this IServiceCollection services)
{
services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssembly(typeof(OrderingModule).Assembly));
services.AddScoped<IOrderingModuleApi, OrderingModuleApi>();
services.AddDbContext<OrderingDbContext>();
return services;
}
}
```
### Event Types
| Type | Scope | Use Case |
| --- | --- | --- |
| Domain Event | Within module | Aggregate state changes |
| Integration Event | Cross-module | Notify other modules of changes |
##Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.