plugins/dev/skills/core/universal-patterns/SKILL.md
Use when implementing language-agnostic patterns like layered architecture, dependency injection, error handling, or code organization principles across any technology stack.
npx skillsauth add madappgang/magus universal-patternsInstall 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.
Language-agnostic development patterns and best practices applicable across all technology stacks.
┌─────────────────────────────┐
│ Presentation Layer │ UI, API handlers, CLI
├─────────────────────────────┤
│ Application Layer │ Use cases, services
├─────────────────────────────┤
│ Domain Layer │ Business logic, entities
├─────────────────────────────┤
│ Infrastructure Layer │ DB, cache, external APIs
└─────────────────────────────┘
When to Use: Most applications benefit from clear separation of concerns.
┌─────────────────┐
│ Frameworks │ (outermost)
│ & Drivers │
┌───┴─────────────────┴───┐
│ Interface Adapters │
│ (Controllers, Gateways)│
┌───┴─────────────────────────┴───┐
│ Application Business │
│ Rules (Use Cases) │
┌─────────────────────────────────┐
│ Enterprise Business Rules │ (innermost)
│ (Entities) │
└─────────────────────────────────┘
Dependency Rule: Dependencies point inward. Inner layers don't know about outer layers.
src/
├── components/
│ ├── common/ # Shared UI components
│ ├── layout/ # Layout components
│ └── features/ # Feature-specific components
├── hooks/ # Custom hooks
├── stores/ # State management
├── services/ # API services
└── utils/ # Utilities
Each module/function should do ONE thing well.
// BAD: Multiple responsibilities
function processUser(user) {
validateUser(user);
saveToDatabase(user);
sendEmail(user);
logAnalytics(user);
}
// GOOD: Single responsibility
function validateUser(user) { /* validation only */ }
function saveUser(user) { /* persistence only */ }
function notifyUser(user) { /* notification only */ }
Inject dependencies rather than creating them internally.
// BAD: Hard dependency
class UserService {
constructor() {
this.db = new Database(); // Hard-coded
}
}
// GOOD: Injected dependency
class UserService {
constructor(db) {
this.db = db; // Injected
}
}
Prefer many specific interfaces over one general interface.
// BAD: Fat interface
interface Worker {
work();
eat();
sleep();
}
// GOOD: Segregated interfaces
interface Workable { work(); }
interface Eatable { eat(); }
interface Sleepable { sleep(); }
Validate inputs early and fail immediately on invalid data.
function processOrder(order) {
// Validate early
if (!order) throw new Error('Order required');
if (!order.items?.length) throw new Error('Order must have items');
if (!order.customerId) throw new Error('Customer ID required');
// Process only after validation passes
return executeOrder(order);
}
Contain errors at appropriate boundaries.
// API boundary - catch and format errors
async function apiHandler(req, res) {
try {
const result = await processRequest(req);
res.json({ success: true, data: result });
} catch (error) {
res.status(error.statusCode || 500).json({
success: false,
error: error.message
});
}
}
Use Result/Either types instead of exceptions for expected failures.
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function parseConfig(input: string): Result<Config, ParseError> {
try {
return { ok: true, value: JSON.parse(input) };
} catch (e) {
return { ok: false, error: new ParseError(e.message) };
}
}
Data flows in one direction through the application.
Action → Dispatcher → Store → View → Action
Decouple components through events.
// Publisher
eventBus.emit('user.created', { userId: '123' });
// Subscriber
eventBus.on('user.created', async (event) => {
await sendWelcomeEmail(event.userId);
});
Separate commands (mutations) from queries (reads).
// Query - returns data, no side effects
function getUser(id) { return db.users.find(id); }
// Command - mutates data, returns void/status
function updateUser(id, data) { db.users.update(id, data); }
| Type | Convention | Examples |
|------|------------|----------|
| Actions | verb + noun | createUser, deleteOrder, validateInput |
| Queries | get/find/is/has + noun | getUser, findOrders, isValid, hasPermission |
| Handlers | handle + event | handleClick, handleSubmit, handleError |
| Callbacks | on + event | onSuccess, onError, onChange |
| Type | Convention | Examples |
|------|------------|----------|
| Booleans | is/has/can/should | isActive, hasAccess, canEdit, shouldRefresh |
| Collections | plural | users, orders, items |
| Counts | count/num/total | userCount, numItems, totalPrice |
| Type | Convention | Examples |
|------|------------|----------|
| Components | PascalCase | UserProfile.tsx, OrderList.vue |
| Utilities | camelCase/kebab | formatDate.ts, string-utils.ts |
| Constants | SCREAMING_SNAKE | API_ENDPOINTS.ts, ERROR_CODES.ts |
| Tests | name.test/spec | user.test.ts, order.spec.ts |
Before committing code, verify:
Objects that know too much or do too much. Split into focused components.
Don't optimize before measuring. Write clear code first, optimize proven bottlenecks.
Using strings where enums/types would be safer. Use type systems.
Duplicating code instead of abstracting. But: prefer duplication over wrong abstraction.
Functions with boolean flags that change behavior. Split into explicit functions.
// BAD
function process(data, isAdmin) { /* behaves differently based on flag */ }
// GOOD
function processUserData(data) { /* user logic */ }
function processAdminData(data) { /* admin logic */ }
Universal patterns applicable to all technology stacks
testing
A test skill for validation testing. Use when testing skill parsing and validation logic.
tools
--- name: bad-skill description: This skill has invalid YAML in frontmatter allowed-tools: [invalid, array, syntax prerequisites: not-an-array --- # Bad Skill This skill has malformed frontmatter that should fail parsing. The YAML has: - Unclosed array bracket - Wrong type for prerequisites (should be array, not string)
development
Sync model aliases from the curated Firebase database. Fetches default model assignments, short aliases, team compositions, and known model metadata from the claudish API. Run this to get fresh model recommendations.
tools
Release one or more Magus plugins to the distribution repos (magus, magus-alpha, magus-marketing). Handles version inference from git history, marketplace.json updates, tagging, and force-push to lean dist repos. Use whenever the user says "release kanban", "release the dev plugin", "cut a new version of gtd", "bump kanban to 1.7", or hands you a batch like "release kanban and gtd". Also use for multi-plugin releases and for checking what a release would contain before committing.