vibes-plug 1.0.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.github/workflows/publish.yml +20 -0
  2. package/AGENTS.md +66 -0
  3. package/BLUEPRINT.md +152 -60
  4. package/CHANGELOG.md +50 -0
  5. package/README.md +346 -194
  6. package/package.json +25 -25
  7. package/plugin.json +1 -1
  8. package/skills/ai-cost-token-optimizer/SKILL.md +52 -0
  9. package/skills/ai-llm-integration-expert/SKILL.md +180 -162
  10. package/skills/api-design-expert/SKILL.md +314 -310
  11. package/skills/app-analyzer-optimizer/SKILL.md +193 -189
  12. package/skills/apple-ecosystem-expert/SKILL.md +142 -0
  13. package/skills/async-queue-temporal-expert/SKILL.md +54 -0
  14. package/skills/authentication-identity-expert/SKILL.md +251 -20
  15. package/skills/auto-doc-updater/SKILL.md +214 -204
  16. package/skills/autonomous-chaos-monkey/SKILL.md +63 -0
  17. package/skills/autonomous-red-teamer/SKILL.md +59 -0
  18. package/skills/autonomous-swarm-director/SKILL.md +69 -0
  19. package/skills/autonomous-tdd-debugger/SKILL.md +65 -0
  20. package/skills/bootstrap-to-modern/SKILL.md +90 -86
  21. package/skills/brainstorming/SKILL.md +373 -353
  22. package/skills/browser-automation-expert/SKILL.md +46 -0
  23. package/skills/ci-cd-devops-architect/SKILL.md +72 -45
  24. package/skills/cloud-hosting-expert/SKILL.md +244 -244
  25. package/skills/coderabbit/SKILL.md +192 -192
  26. package/skills/cron-scheduler-expert/SKILL.md +298 -0
  27. package/skills/data-telemetry-expert/SKILL.md +213 -213
  28. package/skills/database-orm-expert/SKILL.md +294 -294
  29. package/skills/dependency-upgrade-migrator/SKILL.md +295 -0
  30. package/skills/design-system-architect/SKILL.md +27 -10
  31. package/skills/doku-mcp-server/SKILL.md +251 -0
  32. package/skills/doku-payment-gateway/SKILL.md +227 -0
  33. package/skills/e2e-testing-expert/SKILL.md +315 -315
  34. package/skills/edge-serverless-db-expert/SKILL.md +43 -0
  35. package/skills/email-notification-expert/SKILL.md +362 -0
  36. package/skills/error-resilience-expert/SKILL.md +480 -0
  37. package/skills/event-driven-architect/SKILL.md +81 -81
  38. package/skills/feature-flag-analytics-expert/SKILL.md +46 -0
  39. package/skills/file-upload-media-expert/SKILL.md +431 -0
  40. package/skills/form-validation-expert/SKILL.md +401 -0
  41. package/skills/fullstack-expert/SKILL.md +202 -202
  42. package/skills/fullstack-expert/references/api_design_guide.md +466 -466
  43. package/skills/fullstack-expert/references/multi_language_backend.md +528 -528
  44. package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -253
  45. package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -326
  46. package/skills/gemini-agent-booster/SKILL.md +135 -135
  47. package/skills/global-a11y-i18n-expert/SKILL.md +81 -81
  48. package/skills/glsl-shader-expert/SKILL.md +101 -0
  49. package/skills/go-programming-expert/SKILL.md +295 -295
  50. package/skills/graphql-apollo-expert/SKILL.md +108 -0
  51. package/skills/hig/SKILL.md +188 -188
  52. package/skills/hyper-context-synthesizer/SKILL.md +55 -0
  53. package/skills/js-backend-expert/SKILL.md +34 -9
  54. package/skills/legacy-code-translator/SKILL.md +65 -0
  55. package/skills/llm-cost-arbitrage-router/SKILL.md +59 -0
  56. package/skills/logging-error-tracking-expert/SKILL.md +338 -0
  57. package/skills/mcp-client-orchestrator/SKILL.md +70 -0
  58. package/skills/mcp-server-architect/SKILL.md +194 -194
  59. package/skills/micro-frontend-architect/SKILL.md +106 -0
  60. package/skills/mobile-expo-expert/SKILL.md +186 -186
  61. package/skills/mobile-push-notification-expert/SKILL.md +51 -0
  62. package/skills/monday-design-aesthetic/SKILL.md +67 -67
  63. package/skills/monorepo-architect/SKILL.md +227 -227
  64. package/skills/mpa-orchestrator/SKILL.md +101 -101
  65. package/skills/multi-agent-orchestration/SKILL.md +234 -234
  66. package/skills/multiple-entry-points/SKILL.md +55 -55
  67. package/skills/mvc-expert/SKILL.md +231 -231
  68. package/skills/payment-gateway-expert/SKILL.md +45 -45
  69. package/skills/performance-web-vitals/SKILL.md +332 -332
  70. package/skills/post-quantum-crypto-migrator/SKILL.md +57 -0
  71. package/skills/prd-architect/SKILL.md +201 -191
  72. package/skills/proactive-background-watcher/SKILL.md +62 -0
  73. package/skills/production-ready-hardener/PRODUCTION_READINESS_REPORT.md +67 -0
  74. package/skills/production-ready-hardener/SKILL.md +173 -186
  75. package/skills/production-ready-hardener/references/production_checklist.md +161 -161
  76. package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +881 -875
  77. package/skills/project-context-mapper/SKILL.md +79 -0
  78. package/skills/python-programming-expert/SKILL.md +263 -132
  79. package/skills/rate-limit-abuse-prevention/SKILL.md +371 -0
  80. package/skills/realtime-collaboration-expert/SKILL.md +45 -45
  81. package/skills/rust-programming-expert/SKILL.md +235 -235
  82. package/skills/saas-billing/SKILL.md +377 -377
  83. package/skills/saas-multi-tenant/SKILL.md +251 -237
  84. package/skills/saas-mvp-launcher/SKILL.md +10 -0
  85. package/skills/saas-transformer/SKILL.md +187 -144
  86. package/skills/saas-transformer/references/billing_integration_guide.md +401 -401
  87. package/skills/saas-transformer/references/feature_gating_patterns.md +137 -137
  88. package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -121
  89. package/skills/saas-transformer/scripts/saas_transformation_scanner.py +39 -29
  90. package/skills/scalability-clean-code/SKILL.md +229 -229
  91. package/skills/self-evolving-memory-graph/SKILL.md +75 -0
  92. package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -0
  93. package/skills/senior-frontend/SKILL.md +161 -161
  94. package/skills/senior-fullstack/SKILL.md +167 -167
  95. package/skills/seo/SKILL.md +235 -225
  96. package/skills/seo-geo/SKILL.md +188 -188
  97. package/skills/session-context-loader/SKILL.md +77 -0
  98. package/skills/session-handoff-resume/SKILL.md +158 -158
  99. package/skills/skill_baru/SKILL.md +172 -147
  100. package/skills/spa-orchestrator/SKILL.md +288 -288
  101. package/skills/state-management-expert/SKILL.md +272 -272
  102. package/skills/supabase-security-expert/SKILL.md +243 -243
  103. package/skills/tailwind-expert/SKILL.md +188 -188
  104. package/skills/tanstack-query-expert/SKILL.md +199 -199
  105. package/skills/token-saver/SKILL.md +119 -111
  106. package/skills/typescript-expert/SKILL.md +324 -279
  107. package/skills/ui-components-expert/SKILL.md +263 -46
  108. package/skills/ui-ux-pro-max/SKILL.md +202 -201
  109. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  110. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  111. package/skills/ui_ux_expert/SKILL.md +17 -6
  112. package/skills/vector-db-rag-expert/SKILL.md +52 -0
  113. package/skills/vibe-code-gardener/SKILL.md +181 -173
  114. package/skills/visual-qa-vision-agent/SKILL.md +65 -0
  115. package/skills/vue-frontend-expert/SKILL.md +126 -0
  116. package/skills/web-3d-graphics-expert/SKILL.md +131 -0
  117. package/skills/web-game-engine-expert/SKILL.md +96 -0
  118. package/skills/web-scraper/SKILL.md +207 -205
  119. package/skills/website-design-cloner/SKILL.md +174 -0
  120. package/skills/webxr-ar-vr-expert/SKILL.md +117 -0
  121. package/skills/zero-to-prod-orchestrator/SKILL.md +206 -180
  122. package/skills/zero-trust-secret-vault/SKILL.md +40 -0
  123. package/vibes-swarm-demo.gif +0 -0
@@ -12,9 +12,15 @@ import re
12
12
  from pathlib import Path
13
13
  from typing import Dict, List
14
14
 
15
+ # Ensure UTF-8 output on Windows consoles
16
+ if hasattr(sys.stdout, 'reconfigure'):
17
+ sys.stdout.reconfigure(encoding='utf-8')
18
+ if hasattr(sys.stderr, 'reconfigure'):
19
+ sys.stderr.reconfigure(encoding='utf-8')
20
+
15
21
 
16
22
  class SaasTransformationScanner:
17
- """Scans an existing codebase for SaaS transformation readiness across 8 pillars."""
23
+ """Scans an existing codebase for SaaS transformation readiness across 7 key pillars."""
18
24
 
19
25
  PILLAR_WEIGHTS = {
20
26
  'tenancy': 0.20,
@@ -108,14 +114,14 @@ class SaasTransformationScanner:
108
114
 
109
115
  def _grep_project(self, pattern: str, extensions: List[str] = None) -> List[str]:
110
116
  matches = []
111
- exts = extensions or ['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.prisma']
117
+ exts = extensions or ['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.prisma', '.sql', '.yaml', '.yml', '.json']
112
118
  for ext in exts:
113
119
  for f in self.target_path.rglob(f'*{ext}'):
114
- if any(x in str(f) for x in ['node_modules', '.next', 'dist', '.git']):
120
+ if any(x in str(f) for x in ['node_modules', '.next', 'dist', '.git', 'target', '.venv']):
115
121
  continue
116
122
  try:
117
- content = f.read_text(errors='ignore')
118
- if re.search(pattern, content):
123
+ content = f.read_text(encoding='utf-8', errors='ignore')
124
+ if re.search(pattern, content, re.IGNORECASE):
119
125
  matches.append(str(f.relative_to(self.target_path)))
120
126
  except (IOError, OSError):
121
127
  continue
@@ -125,91 +131,95 @@ class SaasTransformationScanner:
125
131
  p = self._init_pillar('tenancy', 'Multi-Tenancy Foundation')
126
132
 
127
133
  # Check database schema structure
128
- has_db_schema = self._file_exists('prisma/schema.prisma') or self._grep_project('pgTable|sqliteTable|mysqlTable', ['.ts', '.js'])
129
- self._check(p, 'Database schema config exists', has_db_schema, severity='critical')
134
+ has_db_schema = self._file_exists('prisma/schema.prisma', 'drizzle.config.ts', 'drizzle.config.js') or self._grep_project(r'pgTable|sqliteTable|mysqlTable|schema\.createTable|Base\.metadata', ['.ts', '.js', '.py'])
135
+ self._check(p, 'Database schema config exists', bool(has_db_schema), severity='critical')
130
136
 
131
137
  # Check tenant id usage
132
- tenant_cols = self._grep_project(r'tenant_id|tenantId|workspace_id|workspaceId', ['.prisma', '.ts', '.js'])
138
+ tenant_cols = self._grep_project(r'tenant_id|tenantId|workspace_id|workspaceId|org_id|orgId', ['.prisma', '.ts', '.js', '.py', '.go', '.sql'])
133
139
  self._check(p, 'tenant_id/workspace_id column configured in models', len(tenant_cols) > 0, severity='critical')
134
140
 
135
141
  # Check RLS
136
- has_rls = self._grep_project(r'ROW LEVEL SECURITY|ENABLE RLS|enableRowLevelSecurity', ['.sql', '.ts', '.js'])
137
- self._check(p, 'PostgreSQL RLS setup or database policies present', len(has_rls) > 0)
142
+ has_rls = self._grep_project(r'ROW LEVEL SECURITY|ENABLE RLS|enableRowLevelSecurity|createPolicy', ['.sql', '.ts', '.js', '.py'])
143
+ self._check(p, 'PostgreSQL RLS setup or database isolation policies present', len(has_rls) > 0)
138
144
 
139
145
  # Check Tenant Middleware
140
- has_mw = self._grep_project(r'tenantMiddleware|app\.current_tenant_id|tenantContext', ['.ts', '.js', '.py', '.go'])
146
+ has_mw = self._grep_project(r'tenantMiddleware|app\.current_tenant_id|tenantContext|workspaceMiddleware', ['.ts', '.js', '.py', '.go'])
141
147
  self._check(p, 'Tenant-aware middleware initialized', len(has_mw) > 0)
142
148
 
143
149
  def _audit_auth(self):
144
150
  p = self._init_pillar('auth', 'Authentication & Authorization')
145
151
 
146
152
  # Auth service provider detection
147
- has_clerk = self._grep_project(r'clerkMiddleware|@clerk/nextjs', ['.ts', '.tsx', '.json'])
148
- has_nextauth = self._grep_project(r'NextAuth|auth\.js', ['.ts', '.js'])
149
- has_supabase_auth = self._grep_project(r'supabase\.auth|@supabase/ssr', ['.ts', '.tsx', '.js'])
150
- self._check(p, 'Production auth provider configured (Clerk/NextAuth/Supabase Auth)',
151
- bool(has_clerk or has_nextauth or has_supabase_auth), severity='critical')
153
+ has_clerk = self._grep_project(r'clerkMiddleware|@clerk/nextjs|@clerk/clerk-sdk-node', ['.ts', '.tsx', '.json'])
154
+ has_nextauth = self._grep_project(r'NextAuth|auth\.js|@auth/core|next-auth', ['.ts', '.js', '.json'])
155
+ has_supabase_auth = self._grep_project(r'supabase\.auth|@supabase/ssr|@supabase/auth-helpers', ['.ts', '.tsx', '.js'])
156
+ has_firebase_auth = self._grep_project(r'firebase/auth|firebase-admin/auth', ['.ts', '.tsx', '.js', '.json'])
157
+ has_custom_jwt = self._grep_project(r'jsonwebtoken|jose|PyJWT', ['.ts', '.js', '.py', '.json'])
158
+
159
+ has_auth_provider = bool(has_clerk or has_nextauth or has_supabase_auth or has_firebase_auth or has_custom_jwt)
160
+ self._check(p, 'Production auth provider configured (Clerk/NextAuth/Supabase/Firebase/JWT)',
161
+ has_auth_provider, severity='critical')
152
162
 
153
163
  # Roles / RBAC
154
- has_roles = self._grep_project(r'role\s*:\s*["\'](admin|owner|member)["\']|requireRole|checkPermission', ['.ts', '.tsx', '.js', '.py'])
164
+ has_roles = self._grep_project(r'role\s*:\s*["\'](admin|owner|member|viewer)["\']|requireRole|checkPermission|hasPermission|RBAC', ['.ts', '.tsx', '.js', '.py', '.go'])
155
165
  self._check(p, 'Role-Based Access Control (RBAC) definitions exist', len(has_roles) > 0)
156
166
 
157
167
  def _audit_billing(self):
158
168
  p = self._init_pillar('billing', 'Billing & Subscription')
159
169
 
160
170
  # Payment Provider dependencies
161
- has_stripe = self._grep_project(r'stripe|lemonsqueezy|paddle-sdk', ['.json', '.ts', '.js', '.py'])
162
- self._check(p, 'Payment processor integrated (Stripe/LemonSqueezy)', len(has_stripe) > 0, severity='critical')
171
+ has_stripe = self._grep_project(r'stripe|lemonsqueezy|paddle-sdk|doku-payment|midtrans', ['.json', '.ts', '.js', '.py', '.go'])
172
+ self._check(p, 'Payment processor integrated (Stripe/LemonSqueezy/DOKU/Midtrans)', len(has_stripe) > 0, severity='critical')
163
173
 
164
174
  # Webhooks
165
- has_webhook = self._grep_project(r'stripe\.webhooks|constructEvent|webhooks/stripe', ['.ts', '.js', '.py'])
175
+ has_webhook = self._grep_project(r'stripe\.webhooks|constructEvent|webhooks/stripe|doku.*webhook|verifySignature', ['.ts', '.js', '.py', '.go'])
166
176
  self._check(p, 'Webhook listener for payment events implemented', len(has_webhook) > 0)
167
177
 
168
178
  # Pricing and Plans config
169
- has_pricing = self._grep_project(r'pricing|plans|subscriptionStatus|tier', ['.ts', '.tsx', '.js'])
179
+ has_pricing = self._grep_project(r'pricing|plans|subscriptionStatus|tier|PLAN_LIMITS', ['.ts', '.tsx', '.js', '.py'])
170
180
  self._check(p, 'Pricing plan definitions present', len(has_pricing) > 0)
171
181
 
172
182
  def _audit_teams(self):
173
183
  p = self._init_pillar('teams', 'Workspace & Team Management')
174
184
 
175
185
  # Member list / Workspace switcher check
176
- has_switcher = self._grep_project(r'workspaceSwitcher|WorkspaceSelect|switchWorkspace', ['.tsx', '.ts', '.js'])
186
+ has_switcher = self._grep_project(r'workspaceSwitcher|WorkspaceSelect|switchWorkspace|orgSwitcher', ['.tsx', '.ts', '.js'])
177
187
  self._check(p, 'Workspace switching controls found', len(has_switcher) > 0)
178
188
 
179
189
  # Invite flow
180
- has_invites = self._grep_project(r'workspace_invitations|inviteMember|invitationToken', ['.prisma', '.ts', '.js'])
190
+ has_invites = self._grep_project(r'workspace_invitations|inviteMember|invitationToken|team_members', ['.prisma', '.ts', '.js', '.py', '.sql'])
181
191
  self._check(p, 'Team invitation system models or methods exist', len(has_invites) > 0)
182
192
 
183
193
  def _audit_frontend(self):
184
194
  p = self._init_pillar('frontend', 'SaaS App Shell & Dashboard')
185
195
 
186
196
  # Shell and settings pages
187
- has_billing_ui = self._grep_project(r'/settings/billing|BillingSettings', ['.tsx', '.ts', '.js'])
197
+ has_billing_ui = self._grep_project(r'/settings/billing|BillingSettings|SubscriptionSettings', ['.tsx', '.ts', '.js'])
188
198
  self._check(p, 'Billing/subscription settings page implemented', len(has_billing_ui) > 0)
189
199
 
190
- has_team_ui = self._grep_project(r'/settings/team|TeamSettings', ['.tsx', '.ts', '.js'])
200
+ has_team_ui = self._grep_project(r'/settings/team|TeamSettings|MembersSettings', ['.tsx', '.ts', '.js'])
191
201
  self._check(p, 'Team/member settings page implemented', len(has_team_ui) > 0)
192
202
 
193
203
  def _audit_api(self):
194
204
  p = self._init_pillar('api', 'API Layer & Feature Gating')
195
205
 
196
206
  # Gated flags or plan limits
197
- has_gating = self._grep_project(r'PLAN_LIMITS|PLAN_CONFIGS|hasFeature|assertHasFeature', ['.ts', '.tsx', '.js'])
207
+ has_gating = self._grep_project(r'PLAN_LIMITS|PLAN_CONFIGS|hasFeature|assertHasFeature|useFeatureFlag|checkFeatureGating', ['.ts', '.tsx', '.js', '.py'])
198
208
  self._check(p, 'Feature gating / usage limit configuration map defined', len(has_gating) > 0)
199
209
 
200
210
  # Usage metering log
201
- has_metering = self._grep_project(r'usage_records|usageRecords|usageMeter|incrementUsage', ['.prisma', '.ts', '.js'])
211
+ has_metering = self._grep_project(r'usage_records|usageRecords|usageMeter|incrementUsage|trackUsage', ['.prisma', '.ts', '.js', '.py', '.sql'])
202
212
  self._check(p, 'Usage metering / metric tracking database model exists', len(has_metering) > 0)
203
213
 
204
214
  def _audit_hardening(self):
205
215
  p = self._init_pillar('hardening', 'Production Hardening')
206
216
 
207
217
  # Basic rate limits
208
- has_rate_limit = self._grep_project(r'rate.?limit|upstash/ratelimit|limiter', ['.ts', '.js', '.py'])
218
+ has_rate_limit = self._grep_project(r'rate.?limit|upstash/ratelimit|limiter|slowDown|governor', ['.ts', '.js', '.py', '.go'])
209
219
  self._check(p, 'API Rate Limiting setup configured', len(has_rate_limit) > 0)
210
220
 
211
221
  # Env validation
212
- has_env_spec = self._file_exists('.env.example', '.env.template')
222
+ has_env_spec = self._file_exists('.env.example', '.env.template', '.env.schema')
213
223
  self._check(p, 'Environment example schema exists', has_env_spec)
214
224
 
215
225
  def _calculate_overall_score(self):
@@ -1,229 +1,229 @@
1
- ---
2
- name: scalability-clean-code
3
- description: "Software architecture guidelines to maintain code readability (Clean Code, SOLID, DRY) and application scalability / Panduan arsitektur perangkat lunak untuk menjaga keterbacaan kode (Clean Code, SOLID, DRY) dan kemampuan skalabilitas aplikasi."
4
- author: "Roedy Rustam"
5
- ---
6
-
7
- # Scalability & Clean Code (2026 Edition)
8
-
9
- [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
-
11
- ---
12
-
13
- <a name="english"></a>
14
- ## English
15
-
16
- ### Description
17
- Software architecture guidelines for writing clean, scalable, and maintainable code. Covers SOLID principles, DRY/YAGNI/KISS, Clean Architecture layers, **Vertical Slice Architecture** (the modern alternative to layered architecture), Domain-Driven Design (DDD) patterns, and practical refactoring techniques.
18
-
19
- ### Trigger Conditions
20
- - Refactoring a codebase that has become hard to understand or modify.
21
- - Designing the architecture for a new feature or service.
22
- - Identifying and eliminating code smells (God Classes, Feature Envy, Long Methods).
23
- - Deciding between Layered Architecture vs Vertical Slice Architecture.
24
- - Applying SOLID principles to a specific code problem.
25
-
26
- ### The SOLID Principles (With Modern Context)
27
-
28
- #### Single Responsibility Principle (SRP)
29
- A module/class/function should have one reason to change. In 2026 React/Node.js context:
30
- - **Bad**: A React component that fetches data, transforms it, and renders UI.
31
- - **Good**: Separate `useUserQuery()` hook (fetch), `transformUser()` util (transform), `UserCard` component (render).
32
-
33
- #### Open/Closed Principle (OCP)
34
- Open for extension, closed for modification. Use composition and strategy pattern:
35
- ```typescript
36
- // Bad: modify existing code every time a new payment provider is added
37
- function processPayment(type: 'stripe' | 'polar' | 'paypal', amount: number) {
38
- if (type === 'stripe') { /* ... */ }
39
- else if (type === 'polar') { /* ... */ }
40
- }
41
-
42
- // Good: extend by adding new providers, not modifying existing code
43
- interface PaymentProvider {
44
- charge(amount: number): Promise<Receipt>;
45
- }
46
-
47
- class StripeProvider implements PaymentProvider { ... }
48
- class PolarProvider implements PaymentProvider { ... }
49
-
50
- function processPayment(provider: PaymentProvider, amount: number) {
51
- return provider.charge(amount);
52
- }
53
- ```
54
-
55
- #### Dependency Inversion Principle (DIP)
56
- High-level modules should not depend on low-level modules — both should depend on abstractions:
57
- ```typescript
58
- // Bad: handler directly imports concrete DB client
59
- import { db } from './postgres-client';
60
-
61
- // Good: inject the repository interface
62
- interface UserRepository {
63
- findById(id: string): Promise<User | null>;
64
- save(user: User): Promise<void>;
65
- }
66
-
67
- async function getUser(repo: UserRepository, id: string) {
68
- return repo.findById(id);
69
- }
70
- ```
71
-
72
- ### Vertical Slice Architecture (VSA)
73
- The modern alternative to traditional layered architecture (Controller → Service → Repository). Organize code by **feature** (vertical slice) rather than by **technical layer** (horizontal slice):
74
-
75
- ```
76
- Traditional (Layered):
77
- src/
78
- controllers/ ← all controllers together
79
- services/ ← all services together
80
- repositories/ ← all repositories together
81
-
82
- Vertical Slice:
83
- src/
84
- features/
85
- users/
86
- create-user.handler.ts ← all logic for "create user" in one place
87
- create-user.schema.ts
88
- create-user.test.ts
89
- products/
90
- list-products.handler.ts
91
- list-products.schema.ts
92
- ```
93
-
94
- **Benefits of VSA**:
95
- - Features are self-contained — easy to add, modify, delete, or move.
96
- - No need to navigate 3-4 layers just to trace one user story.
97
- - Natural boundary for microservice extraction.
98
-
99
- ```typescript
100
- // features/users/create-user.handler.ts
101
- // One file contains the complete "create user" vertical slice
102
- import { z } from 'zod';
103
- import { db } from '@/lib/db';
104
- import { sendWelcomeEmail } from '@/lib/email';
105
-
106
- export const CreateUserSchema = z.object({
107
- name: z.string().min(2),
108
- email: z.string().email(),
109
- });
110
-
111
- export type CreateUserInput = z.infer<typeof CreateUserSchema>;
112
-
113
- export async function handleCreateUser(input: CreateUserInput) {
114
- const validated = CreateUserSchema.parse(input);
115
-
116
- const user = await db.user.create({ data: validated });
117
- await sendWelcomeEmail(user.email, user.name);
118
-
119
- return user;
120
- }
121
- ```
122
-
123
- ### Clean Code Principles
124
-
125
- #### Functions
126
- - **Do one thing**: Functions should do one thing and do it well.
127
- - **Small**: Aim for < 20 lines. If longer, extract sub-functions.
128
- - **Descriptive names**: `getUsersByWorkspace()` not `getData()`.
129
- - **No side effects**: Pure functions are predictable and testable.
130
-
131
- #### Naming
132
- - Variables: noun phrases (`userCount`, `activeWorkspaces`).
133
- - Functions: verb phrases (`fetchUser`, `validateInput`, `sendEmail`).
134
- - Boolean: question form (`isActive`, `hasPermission`, `canEdit`).
135
- - Avoid abbreviations: `workspace` not `ws`, `configuration` not `cfg`.
136
-
137
- #### Comments
138
- - **Don't comment bad code — rewrite it.**
139
- - Write self-documenting code: well-named variables and functions eliminate the need for most comments.
140
- - **Do** comment: why (intent), not what (obvious from code).
141
-
142
- #### DRY, YAGNI, KISS
143
- - **DRY**: Don't Repeat Yourself — extract shared logic. But: avoid premature abstraction.
144
- - **YAGNI**: You Aren't Gonna Need It — don't build features "just in case".
145
- - **KISS**: Keep It Simple, Stupid — the simplest solution that works is usually best.
146
-
147
- ### Code Smells & Refactoring
148
-
149
- | Smell | Symptom | Refactoring |
150
- |---|---|---|
151
- | **God Class** | Class does everything | Extract Class, Move Method |
152
- | **Long Method** | Method > 30 lines | Extract Method |
153
- | **Feature Envy** | Method uses another class's data excessively | Move Method |
154
- | **Data Clumps** | Same 3+ params appear together repeatedly | Introduce Parameter Object |
155
- | **Magic Numbers** | `if (status === 3)` | Extract Constant |
156
- | **Shotgun Surgery** | One change requires edits in many places | Move Method, Inline Class |
157
- | **Primitive Obsession** | Using string/int for domain concepts | Replace with Value Object |
158
-
159
- ### Architecture Decision Framework
160
- When choosing an architecture, ask:
161
- 1. **What changes together?** Organize code that changes together.
162
- 2. **What is independently deployable?** Separate services by deployment boundary.
163
- 3. **What has different scaling needs?** Scale independently only what needs it.
164
- 4. **What is the team size?** Microservices add overhead — start monolith, extract when needed.
165
-
166
- ---
167
-
168
- <a name="bahasa-indonesia"></a>
169
- ## Bahasa Indonesia
170
-
171
- ### Deskripsi
172
- Panduan arsitektur perangkat lunak untuk menulis kode yang bersih, skalabel, dan mudah dirawat. Mencakup prinsip SOLID, DRY/YAGNI/KISS, lapisan Clean Architecture, **Vertical Slice Architecture** (alternatif modern dari layered architecture), pola Domain-Driven Design (DDD), dan teknik refactoring praktis.
173
-
174
- ### Kondisi Pemicu
175
- - Merefaktor codebase yang sulit dipahami atau dimodifikasi.
176
- - Merancang arsitektur untuk fitur atau layanan baru.
177
- - Mengidentifikasi dan menghilangkan code smell (God Class, Feature Envy, Long Method).
178
- - Memutuskan antara Layered Architecture vs Vertical Slice Architecture.
179
- - Menerapkan prinsip SOLID pada masalah kode tertentu.
180
-
181
- ### Prinsip SOLID
182
-
183
- #### SRP — Single Responsibility Principle
184
- Setiap modul/kelas/fungsi harus memiliki satu alasan untuk berubah. Pisahkan pengambilan data, transformasi data, dan rendering UI.
185
-
186
- #### OCP — Open/Closed Principle
187
- Terbuka untuk ekstensi, tertutup untuk modifikasi. Gunakan komposisi dan pola strategi — tambah provider baru tanpa mengubah kode yang ada.
188
-
189
- #### DIP — Dependency Inversion Principle
190
- Modul tingkat tinggi tidak boleh bergantung pada modul tingkat rendah — keduanya harus bergantung pada abstraksi (interface).
191
-
192
- ### Vertical Slice Architecture (VSA)
193
- Alternatif modern dari layered architecture tradisional. Organisasikan kode berdasarkan **fitur** (irisan vertikal), bukan lapisan teknis (irisan horizontal).
194
-
195
- **Keuntungan VSA:**
196
- - Fitur bersifat self-contained — mudah ditambah, dimodifikasi, dihapus, atau dipindah.
197
- - Tidak perlu menavigasi 3-4 layer hanya untuk melacak satu user story.
198
- - Batas natural untuk ekstraksi microservice.
199
-
200
- ### Prinsip Clean Code
201
-
202
- #### Fungsi
203
- - Lakukan satu hal dan lakukan dengan baik.
204
- - Nama deskriptif: `getUsersByWorkspace()` bukan `getData()`.
205
- - Tanpa efek samping: fungsi murni dapat diprediksi dan diuji.
206
-
207
- #### Penamaan
208
- - Variabel: frasa kata benda (`jumlahPengguna`, `workspaceAktif`).
209
- - Fungsi: frasa kata kerja (`ambilPengguna`, `validasiInput`).
210
- - Boolean: bentuk pertanyaan (`aktif`, `punyaIzin`, `bisaEdit`).
211
-
212
- #### Komentar
213
- - Jangan komen kode buruk — tulis ulang.
214
- - Tulis kode yang mendokumentasikan dirinya sendiri.
215
- - Komentar: **mengapa** (niat), bukan apa (jelas dari kode).
216
-
217
- #### DRY, YAGNI, KISS
218
- - **DRY**: Jangan ulangi diri sendiri — ekstrak logika bersama.
219
- - **YAGNI**: Anda tidak akan membutuhkannya — jangan bangun fitur "untuk jaga-jaga".
220
- - **KISS**: Tetap sederhana — solusi paling sederhana yang berfungsi biasanya terbaik.
221
-
222
- ### Code Smell & Refactoring
223
- Identifikasi dan perbaiki: God Class, Long Method, Feature Envy, Data Clumps, Magic Numbers, Shotgun Surgery, Primitive Obsession.
224
-
225
- ### Framework Keputusan Arsitektur
226
- 1. **Apa yang berubah bersama?** Organisasikan kode yang berubah bersama.
227
- 2. **Apa yang dapat di-deploy secara independen?** Pisahkan layanan berdasarkan batas deployment.
228
- 3. **Apa yang memiliki kebutuhan scaling berbeda?** Scale secara independen hanya yang membutuhkannya.
229
- 4. **Berapa besar tim?** Microservices menambah overhead — mulai monolith, ekstrak saat diperlukan.
1
+ ---
2
+ name: scalability-clean-code
3
+ description: "Software architecture guidelines to maintain code readability (Clean Code, SOLID, DRY) and application scalability / Panduan arsitektur perangkat lunak untuk menjaga keterbacaan kode (Clean Code, SOLID, DRY) dan kemampuan skalabilitas aplikasi."
4
+ author: "Roedy Rustam"
5
+ ---
6
+
7
+ # Scalability & Clean Code (2026 Edition)
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Description
17
+ Software architecture guidelines for writing clean, scalable, and maintainable code. Covers SOLID principles, DRY/YAGNI/KISS, Clean Architecture layers, **Vertical Slice Architecture** (the modern alternative to layered architecture), Domain-Driven Design (DDD) patterns, and practical refactoring techniques.
18
+
19
+ ### Trigger Conditions
20
+ - Refactoring a codebase that has become hard to understand or modify.
21
+ - Designing the architecture for a new feature or service.
22
+ - Identifying and eliminating code smells (God Classes, Feature Envy, Long Methods).
23
+ - Deciding between Layered Architecture vs Vertical Slice Architecture.
24
+ - Applying SOLID principles to a specific code problem.
25
+
26
+ ### The SOLID Principles (With Modern Context)
27
+
28
+ #### Single Responsibility Principle (SRP)
29
+ A module/class/function should have one reason to change. In 2026 React/Node.js context:
30
+ - **Bad**: A React component that fetches data, transforms it, and renders UI.
31
+ - **Good**: Separate `useUserQuery()` hook (fetch), `transformUser()` util (transform), `UserCard` component (render).
32
+
33
+ #### Open/Closed Principle (OCP)
34
+ Open for extension, closed for modification. Use composition and strategy pattern:
35
+ ```typescript
36
+ // Bad: modify existing code every time a new payment provider is added
37
+ function processPayment(type: 'stripe' | 'polar' | 'paypal', amount: number) {
38
+ if (type === 'stripe') { /* ... */ }
39
+ else if (type === 'polar') { /* ... */ }
40
+ }
41
+
42
+ // Good: extend by adding new providers, not modifying existing code
43
+ interface PaymentProvider {
44
+ charge(amount: number): Promise<Receipt>;
45
+ }
46
+
47
+ class StripeProvider implements PaymentProvider { ... }
48
+ class PolarProvider implements PaymentProvider { ... }
49
+
50
+ function processPayment(provider: PaymentProvider, amount: number) {
51
+ return provider.charge(amount);
52
+ }
53
+ ```
54
+
55
+ #### Dependency Inversion Principle (DIP)
56
+ High-level modules should not depend on low-level modules — both should depend on abstractions:
57
+ ```typescript
58
+ // Bad: handler directly imports concrete DB client
59
+ import { db } from './postgres-client';
60
+
61
+ // Good: inject the repository interface
62
+ interface UserRepository {
63
+ findById(id: string): Promise<User | null>;
64
+ save(user: User): Promise<void>;
65
+ }
66
+
67
+ async function getUser(repo: UserRepository, id: string) {
68
+ return repo.findById(id);
69
+ }
70
+ ```
71
+
72
+ ### Vertical Slice Architecture (VSA)
73
+ The modern alternative to traditional layered architecture (Controller → Service → Repository). Organize code by **feature** (vertical slice) rather than by **technical layer** (horizontal slice):
74
+
75
+ ```
76
+ Traditional (Layered):
77
+ src/
78
+ controllers/ ← all controllers together
79
+ services/ ← all services together
80
+ repositories/ ← all repositories together
81
+
82
+ Vertical Slice:
83
+ src/
84
+ features/
85
+ users/
86
+ create-user.handler.ts ← all logic for "create user" in one place
87
+ create-user.schema.ts
88
+ create-user.test.ts
89
+ products/
90
+ list-products.handler.ts
91
+ list-products.schema.ts
92
+ ```
93
+
94
+ **Benefits of VSA**:
95
+ - Features are self-contained — easy to add, modify, delete, or move.
96
+ - No need to navigate 3-4 layers just to trace one user story.
97
+ - Natural boundary for microservice extraction.
98
+
99
+ ```typescript
100
+ // features/users/create-user.handler.ts
101
+ // One file contains the complete "create user" vertical slice
102
+ import { z } from 'zod';
103
+ import { db } from '@/lib/db';
104
+ import { sendWelcomeEmail } from '@/lib/email';
105
+
106
+ export const CreateUserSchema = z.object({
107
+ name: z.string().min(2),
108
+ email: z.string().email(),
109
+ });
110
+
111
+ export type CreateUserInput = z.infer<typeof CreateUserSchema>;
112
+
113
+ export async function handleCreateUser(input: CreateUserInput) {
114
+ const validated = CreateUserSchema.parse(input);
115
+
116
+ const user = await db.user.create({ data: validated });
117
+ await sendWelcomeEmail(user.email, user.name);
118
+
119
+ return user;
120
+ }
121
+ ```
122
+
123
+ ### Clean Code Principles
124
+
125
+ #### Functions
126
+ - **Do one thing**: Functions should do one thing and do it well.
127
+ - **Small**: Aim for < 20 lines. If longer, extract sub-functions.
128
+ - **Descriptive names**: `getUsersByWorkspace()` not `getData()`.
129
+ - **No side effects**: Pure functions are predictable and testable.
130
+
131
+ #### Naming
132
+ - Variables: noun phrases (`userCount`, `activeWorkspaces`).
133
+ - Functions: verb phrases (`fetchUser`, `validateInput`, `sendEmail`).
134
+ - Boolean: question form (`isActive`, `hasPermission`, `canEdit`).
135
+ - Avoid abbreviations: `workspace` not `ws`, `configuration` not `cfg`.
136
+
137
+ #### Comments
138
+ - **Don't comment bad code — rewrite it.**
139
+ - Write self-documenting code: well-named variables and functions eliminate the need for most comments.
140
+ - **Do** comment: why (intent), not what (obvious from code).
141
+
142
+ #### DRY, YAGNI, KISS
143
+ - **DRY**: Don't Repeat Yourself — extract shared logic. But: avoid premature abstraction.
144
+ - **YAGNI**: You Aren't Gonna Need It — don't build features "just in case".
145
+ - **KISS**: Keep It Simple, Stupid — the simplest solution that works is usually best.
146
+
147
+ ### Code Smells & Refactoring
148
+
149
+ | Smell | Symptom | Refactoring |
150
+ |---|---|---|
151
+ | **God Class** | Class does everything | Extract Class, Move Method |
152
+ | **Long Method** | Method > 30 lines | Extract Method |
153
+ | **Feature Envy** | Method uses another class's data excessively | Move Method |
154
+ | **Data Clumps** | Same 3+ params appear together repeatedly | Introduce Parameter Object |
155
+ | **Magic Numbers** | `if (status === 3)` | Extract Constant |
156
+ | **Shotgun Surgery** | One change requires edits in many places | Move Method, Inline Class |
157
+ | **Primitive Obsession** | Using string/int for domain concepts | Replace with Value Object |
158
+
159
+ ### Architecture Decision Framework
160
+ When choosing an architecture, ask:
161
+ 1. **What changes together?** Organize code that changes together.
162
+ 2. **What is independently deployable?** Separate services by deployment boundary.
163
+ 3. **What has different scaling needs?** Scale independently only what needs it.
164
+ 4. **What is the team size?** Microservices add overhead — start monolith, extract when needed.
165
+
166
+ ---
167
+
168
+ <a name="bahasa-indonesia"></a>
169
+ ## Bahasa Indonesia
170
+
171
+ ### Deskripsi
172
+ Panduan arsitektur perangkat lunak untuk menulis kode yang bersih, skalabel, dan mudah dirawat. Mencakup prinsip SOLID, DRY/YAGNI/KISS, lapisan Clean Architecture, **Vertical Slice Architecture** (alternatif modern dari layered architecture), pola Domain-Driven Design (DDD), dan teknik refactoring praktis.
173
+
174
+ ### Kondisi Pemicu
175
+ - Merefaktor codebase yang sulit dipahami atau dimodifikasi.
176
+ - Merancang arsitektur untuk fitur atau layanan baru.
177
+ - Mengidentifikasi dan menghilangkan code smell (God Class, Feature Envy, Long Method).
178
+ - Memutuskan antara Layered Architecture vs Vertical Slice Architecture.
179
+ - Menerapkan prinsip SOLID pada masalah kode tertentu.
180
+
181
+ ### Prinsip SOLID
182
+
183
+ #### SRP — Single Responsibility Principle
184
+ Setiap modul/kelas/fungsi harus memiliki satu alasan untuk berubah. Pisahkan pengambilan data, transformasi data, dan rendering UI.
185
+
186
+ #### OCP — Open/Closed Principle
187
+ Terbuka untuk ekstensi, tertutup untuk modifikasi. Gunakan komposisi dan pola strategi — tambah provider baru tanpa mengubah kode yang ada.
188
+
189
+ #### DIP — Dependency Inversion Principle
190
+ Modul tingkat tinggi tidak boleh bergantung pada modul tingkat rendah — keduanya harus bergantung pada abstraksi (interface).
191
+
192
+ ### Vertical Slice Architecture (VSA)
193
+ Alternatif modern dari layered architecture tradisional. Organisasikan kode berdasarkan **fitur** (irisan vertikal), bukan lapisan teknis (irisan horizontal).
194
+
195
+ **Keuntungan VSA:**
196
+ - Fitur bersifat self-contained — mudah ditambah, dimodifikasi, dihapus, atau dipindah.
197
+ - Tidak perlu menavigasi 3-4 layer hanya untuk melacak satu user story.
198
+ - Batas natural untuk ekstraksi microservice.
199
+
200
+ ### Prinsip Clean Code
201
+
202
+ #### Fungsi
203
+ - Lakukan satu hal dan lakukan dengan baik.
204
+ - Nama deskriptif: `getUsersByWorkspace()` bukan `getData()`.
205
+ - Tanpa efek samping: fungsi murni dapat diprediksi dan diuji.
206
+
207
+ #### Penamaan
208
+ - Variabel: frasa kata benda (`jumlahPengguna`, `workspaceAktif`).
209
+ - Fungsi: frasa kata kerja (`ambilPengguna`, `validasiInput`).
210
+ - Boolean: bentuk pertanyaan (`aktif`, `punyaIzin`, `bisaEdit`).
211
+
212
+ #### Komentar
213
+ - Jangan komen kode buruk — tulis ulang.
214
+ - Tulis kode yang mendokumentasikan dirinya sendiri.
215
+ - Komentar: **mengapa** (niat), bukan apa (jelas dari kode).
216
+
217
+ #### DRY, YAGNI, KISS
218
+ - **DRY**: Jangan ulangi diri sendiri — ekstrak logika bersama.
219
+ - **YAGNI**: Anda tidak akan membutuhkannya — jangan bangun fitur "untuk jaga-jaga".
220
+ - **KISS**: Tetap sederhana — solusi paling sederhana yang berfungsi biasanya terbaik.
221
+
222
+ ### Code Smell & Refactoring
223
+ Identifikasi dan perbaiki: God Class, Long Method, Feature Envy, Data Clumps, Magic Numbers, Shotgun Surgery, Primitive Obsession.
224
+
225
+ ### Framework Keputusan Arsitektur
226
+ 1. **Apa yang berubah bersama?** Organisasikan kode yang berubah bersama.
227
+ 2. **Apa yang dapat di-deploy secara independen?** Pisahkan layanan berdasarkan batas deployment.
228
+ 3. **Apa yang memiliki kebutuhan scaling berbeda?** Scale secara independen hanya yang membutuhkannya.
229
+ 4. **Berapa besar tim?** Microservices menambah overhead — mulai monolith, ekstrak saat diperlukan.