xiaohongshu
xiaohongshu
clean-architecture-principles
Enforce clean architecture principles including DRY, YAGNI, KISS, Law of Demeter, and Separation of Concerns. Warns when complexity creeps in and questions unnecessary features. Use when designing architecture, refactoring, code review, or when user mentions architecture, design patterns, complex...
Full skill instructions
Core architectural principles focused on simplicity, maintainability, and avoiding unnecessary complexity.
If a feature is getting complicated, approach the user about it.
Warn when:
Format:
WARNING: This feature is getting complicated. Here's a simpler approach...
Code duplication means failure.
Bad - Duplication:
// Creating user
async function createUser(data: UserInput) {
const user = {
id: generateId(),
...data,
createdAt: new Date(),
updatedAt: new Date()
};
await db.users.insert(user);
await sendEmail(user.email, 'Welcome!');
await logEvent('user_created', user.id);
return user;
}
// Creating admin - DUPLICATED LOGIC
async function createAdmin(data: AdminInput) {
const admin = {
id: generateId(),
...data,
createdAt: new Date(),
updatedAt: new Date(),
role: 'admin'
};
await db.users.insert(admin);
await sendEmail(admin.email, 'Welcome Admin!');
await logEvent('admin_created', admin.id);
return admin;
}
Good - DRY:
// Shared logic extracted
async function createUserAccount(
data: UserInput,
role: 'user' | 'admin' = 'user'
) {
const account = {
id: generateId(),
...data,
role,
createdAt: new Date(),
updatedAt: new Date()
};
await db.users.insert(account);
await sendEmail(account.email, getWelcomeMessage(role));
await logEvent(`${role}_created`, account.id);
return account;
}
// Simple wrappers
const createUser = (data: UserInput) => createUserAccount(data, 'user');
const createAdmin = (data: AdminInput) => createUserAccount(data, 'admin');
Speculation gets rejected.
Bad - Building features "just in case":
interface UserService {
// Currently needed
getUser(id: string): Promise<User>;
// Speculative - might need someday
getAllUsers(): Promise<User[]>;
searchUsers(query: string): Promise<User[]>;
batchUpdateUsers(ids: string[], updates: Partial<User>): Promise<void>;
exportUsersToCSV(): Promise<string>;
importUsersFromCSV(csv: string): Promise<void>;
archiveOldUsers(days: number): Promise<number>;
}
Good - Only what's needed now:
interface UserService {
// Only what's actually needed right now
getUser(id: string): Promise<User>;
}
// Add methods ONLY when requirements emerge
Question everything:
Complexity means rewrite.
Bad - Over-engineered:
// Complex factory pattern for simple task
interface INotificationStrategy {
send(message: string): Promise<void>;
}
class EmailNotificationStrategy implements INotificationStrategy {
async send(message: string): Promise<void> {
await emailService.send(message);
}
}
class SMSNotificationStrategy implements INotificationStrategy {
async send(message: string): Promise<void> {
await smsService.send(message);
}
}
class NotificationContext {
constructor(private strategy: INotificationStrategy) {}
async notify(message: string): Promise<void> {
await this.strategy.send(message);
}
}
class NotificationFactory {
static create(type: 'email' | 'sms'): NotificationContext {
const strategy = type === 'email'
? new EmailNotificationStrategy()
: new SMSNotificationStrategy();
return new NotificationContext(strategy);
}
}
// Usage - overly complex
const notifier = NotificationFactory.create('email');
await notifier.notify('Hello');
Good - Simple:
// Simple function - does the same thing
async function sendNotification(message: string, type: 'email' | 'sms') {
if (type === 'email') {
await emailService.send(message);
} else {
await smsService.send(message);
}
}
// Usage - clear and simple
await sendNotification('Hello', 'email');
Bloat means delete.
Bad - Bloated with unused features:
class User {
// Actually used
id: string;
name: string;
email: string;
// Unused - delete these
nickname?: string;
favoriteColor?: string;
zodiacSign?: string;
lucky Numbers?: number[];
bio?: string;
website?: string;
socialLinks?: Record<string, string>;
}
Good - Only what's needed:
class User {
id: string;
name: string;
email: string;
}
// Add fields only when actually needed
Coupling means refactor.
Bad - Too much coupling:
// Reaching through multiple objects
function displayUserCity(user: User) {
const city = user.profile.address.location.city.name;
console.log(city);
}
// If any intermediate object changes, this breaks
Good - Tell, don't ask:
// User provides what's needed
class User {
getUserCity(): string {
return this.profile.address.getCity();
}
}
function displayUserCity(user: User) {
const city = user.getUserCity();
console.log(city);
}
// Or even simpler
function displayUserCity(city: string) {
console.log(city);
}
Mixed concerns means split.
Bad - Mixed concerns:
// One function doing everything
async function handleUserRegistration(formData: FormData) {
// Validation
if (!formData.email.includes('@')) throw new Error('Invalid email');
if (formData.password.length < 8) throw new Error('Password too short');
// Business logic
const hashedPassword = await bcrypt.hash(formData.password, 10);
const user = {
id: generateId(),
email: formData.email,
password: hashedPassword,
createdAt: new Date()
};
// Data access
await db.users.insert(user);
// Email sending
await sendEmail(user.email, 'Welcome!');
// Analytics
await analytics.track('user_registered', { userId: user.id });
// UI update
showNotification('Registration successful!');
return user;
}
Good - Separated concerns:
// Validation layer
function validateRegistration(data: FormData): void {
if (!data.email.includes('@')) throw new Error('Invalid email');
if (data.password.length < 8) throw new Error('Password too short');
}
// Business logic layer
async function createUser(data: FormData): Promise<User> {
const hashedPassword = await bcrypt.hash(data.password, 10);
return {
id: generateId(),
email: data.email,
password: hashedPassword,
createdAt: new Date()
};
}
// Data access layer
async function saveUser(user: User): Promise<void> {
await db.users.insert(user);
}
// Notification layer
async function notifyNewUser(user: User): Promise<void> {
await sendEmail(user.email, 'Welcome!');
await analytics.track('user_registered', { userId: user.id });
}
// Orchestration - clean and clear
async function handleUserRegistration(formData: FormData) {
validateRegistration(formData);
const user = await createUser(formData);
await saveUser(user);
await notifyNewUser(user);
showNotification('Registration successful!');
return user;
}
Apply to every line of code.
Questions to ask:
Examples:
Bad:
// Including things not needed
import { useEffect, useState, useCallback, useMemo, useRef } from 'react';
function SimpleComponent() {
const [count, setCount] = useState(0);
// useEffect, useCallback, useMemo, useRef not used - remove them
return <div>{count}</div>;
}
Good:
// Only what's needed
import { useState } from 'react';
function SimpleComponent() {
const [count, setCount] = useState(0);
return <div>{count}</div>;
}
Every single time.
Bad - Clever but unclear:
// "Clever" one-liner
const result = users.reduce((a, u) => ({...a, [u.id]: u.posts.filter(p => p.likes > 10).map(p => p.title)}), {});
Good - Clear and understandable:
// Clear multi-step process
const result: Record<string, string[]> = {};
for (const user of users) {
const popularPosts = user.posts.filter(post => post.likes > 10);
const titles = popularPosts.map(post => post.title);
result[user.id] = titles;
}
Always warn when complexity creeps in:
WARNING: This authentication flow is getting complicated with 5+ steps.
Simpler approach:
1. Use existing authentication library (e.g., NextAuth.js)
2. Reduces custom code by 80%
3. Battle-tested security
4. Maintained by community
Current approach requires:
- Custom JWT handling
- Manual token refresh
- Session management
- Security auditing
Recommendation: Use established solution instead.
Never just accept requirements blindly.
Example conversation:
User: "Add a feature where users can export their data to XML, JSON, CSV, and YAML formats"
Response:
"Let me question this requirement:
1. Which format will users actually use?
2. Can we start with just JSON (most common)?
3. Add other formats only if users request them?
Starting simple:
- Implement JSON export first
- Monitor usage
- Add other formats if needed
This approach:
✅ Delivers value faster
✅ Avoids building unused features
✅ Easier to maintain
✅ Can always add more later
Does JSON-only work for the initial release?"
Warn if you detect:
Refactor when:
Code Duplication (DRY violation)
High Coupling (Law of Demeter violation)
Mixed Concerns (SoC violation)
Unnecessary Complexity (KISS violation)
Speculative Code (YAGNI violation)
Before building a feature, ask:
## Feature: [Name]
### Is this really needed?
- [ ] Yes, it's in current requirements
- [ ] No, it's speculative
### Can we make it simpler?
Current approach: [Describe]
Simpler approach: [Describe]
### Does it follow principles?
- [ ] DRY - No code duplication
- [ ] YAGNI - Not speculative
- [ ] KISS - Simple, not complex
- [ ] SoC - Concerns separated
- [ ] Minimalism - Only what's needed
### Warning flags:
- Complexity level: [Low/Medium/High]
- Dependencies added: [Number]
- Lines of code: [Estimate]
### Recommendation:
[Approve / Simplify / Reject with reasons]
Golden Rules:
Question Everything
Avoid Complexity
Follow Principles
Filipino Wisdom
Clarity Always Wins
Remember: The best architecture is the simplest one that solves the actual problem. Don't build what you might need—build what you need now.
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience