| name | architecture-philosophy |
| description | Core architectural principles for StepLeague - modular design, system thinking, future-proofing, and maintenance reduction. Use when designing new features, refactoring code, considering implementation approaches, or making any architectural decisions. Keywords: architecture, design, modular, refactoring, reusable, shadcn, maintenance, future-proof, system. |
Architecture Philosophy Skill
THE MOST IMPORTANT SKILL: This skill defines HOW we build everything.
Every other skill references these principles.
โ ๏ธ Critical: Read This First
Before implementing ANY solution:
- Think systems, not solutions - Will this pattern be needed elsewhere?
- Check existing patterns - Is this already solved in the codebase?
- Consider maintenance - How many places need updating when requirements change?
- Reference other skills - They encode project-specific implementations of these principles
Core Principles
Every solution in StepLeague must follow these principles:
1. ๐งฉ Modular Over Monolithic (MOST CRITICAL)
Build systems, not one-off solutions.
If you're writing code that solves just ONE specific case, you're probably doing it wrong.
Take 5 extra minutes to think: "How can I make this reusable?"
| โ One-Off (BAD) | โ
Modular System (GOOD) |
|---|
| Hardcoded notification for leagues | Generic notification system with event types |
| Custom dropdown for one form | Reusable FormSelect component |
| Inline error handling | Centralized AppError system in src/lib/errors.ts |
Magic numbers (if (count > 50)) | Settings from app_settings table |
| Duplicate validation logic | Shared Zod schemas in /lib/schemas/ |
Questions to ask BEFORE writing code:
- Will this pattern be needed elsewhere? โ Extract it
- Can I extend an existing utility/hook/component? โ Extend, don't duplicate
- Does this belong in a shared location? โ Move it to
/lib/ or /components/ui/
- Am I hardcoding a value that might change? โ Use settings
2. ๐ฎ Future-Thinking
Design for tomorrow, implement for today.
- Settings over hardcoding: Use
app_settings table for configurable values
- Feature flags: Gate new features with
useFeatureFlag()
- Extensible schemas: Add columns that allow future use cases
const MAX_PROXIES = 10;
const maxProxies = useAppSettings('proxy_max_per_user', 10);
3. ๐ก๏ธ Defensive Programming
Assume things will fail. Plan for it.
- Use the error handling system - Reference
error-handling skill
- Graceful degradation - If a feature fails, don't crash the page
- Fallback values - Always have sensible defaults
const branding = await getCachedBranding().catch(() => DEFAULT_BRANDING);
4. ๐ Maintenance Reduction
Less code = less bugs = less maintenance.
| Principle | Example |
|---|
| Use existing libraries | shadcn/ui over custom components |
| Central configuration | badges.ts for all badge colors |
| Registry patterns | CacheRegistry for cache tags |
| Convention over configuration | File-based routing |
Mandatory Patterns
A. Use shadcn/ui Components
ALWAYS prefer shadcn over custom implementations.
import { Dialog } from "@/components/ui/dialog";
import { DropdownMenu } from "@/components/ui/dropdown-menu";
import { toast } from "@/hooks/use-toast";
Installed shadcn components:
toast, dialog, dropdown-menu, input, label
textarea, select, checkbox, tooltip
confirm-dialog (custom wrapper)
Reference: src/components/ui/
B. Use Reusable Form Components
Reference the form-components skill.
import { FormInput, FormSelect, FormCheckbox } from "@/components/ui/form-fields";
C. Use the API Handler Pattern
Reference the api-handler skill.
export const POST = withApiHandler({
auth: 'required',
schema: mySchema,
}, async ({ user, body, adminClient }) => {
return { success: true };
});
D. Use the Error System
Reference the error-handling skill.
throw new AppError({
code: ErrorCode.VALIDATION_FAILED,
message: 'Invalid input',
context: { field: 'email' },
recoverable: true,
});
E. Use CSS Variables for Theming
Reference the design-system skill.
<div className="bg-card text-foreground border-border">
<div className="bg-slate-900 text-slate-300 border-slate-700">
Decision Framework
When implementing any feature, follow this checklist:
Before Writing Code
- Check existing patterns in AGENTS.md
- Search for similar implementations in the codebase
- Review relevant skills in
.agent/skills/
- Consider: Is this a one-off or a pattern?
While Writing Code
- Extract reusable pieces into utilities/components
- Use centralized configuration (settings, registries)
- Add proper error handling with AppError
- Follow the design system for all UI
After Writing Code
- Update documentation if adding new patterns
- Add to design system page if creating UI components
- Reference in AGENTS.md if it's a key pattern
- Create a skill if it's complex enough
Cross-Skill References
| When Working On | Reference Skill |
|---|
| New features | prd-creation |
| API routes | api-handler |
| Database queries | supabase-patterns |
| Error handling | error-handling |
| UI/Styling | design-system |
| Forms | form-components |
| After completion | project-updates |
Anti-Patterns to Avoid
1. The "Quick Fix"
"I'll just add this inline, it's faster"
Why it's bad: Creates tech debt, makes code harder to maintain.
Instead: Take 5 extra minutes to do it properly.
2. The "Special Case"
"This component is unique, it needs custom styling"
Why it's bad: Breaks consistency, harder to theme.
Instead: Use existing components, extend if needed.
3. The "Magic Number"
if (count > 50) { ... }
Why it's bad: Unexplained, not configurable.
Instead: Use settings or named constants.
4. The "Silenced Error"
try { ... } catch { /* ignore */ }
Why it's bad: Hides bugs, makes debugging impossible.
Instead: Use normalizeError() and reportErrorClient().
5. The "Copy-Paste Component"
Creating a new component that's 90% the same as existing one.
Why it's bad: Duplicated code, inconsistent behavior.
Instead: Extract shared logic, use props for variations.
The 3-Time Rule
If you do something 3 times, extract it.
| Count | Action |
|---|
| 1st time | Implement inline |
| 2nd time | Note the pattern |
| 3rd time | Extract to utility/component/skill |
Key Reference Files
| Area | File |
|---|
| Error handling | src/lib/errors.ts |
| API handler | src/lib/api/handler.ts |
| Form components | src/components/ui/form-fields.tsx |
| Badge config | src/lib/badges.ts |
| Cache registry | src/lib/cache/serverCache.ts |
| Menu config | src/lib/menuConfig.ts |
| Theme variables | src/app/globals.css |
| Settings hook | src/hooks/useAppSettings.ts |
Summary
Build systems, not solutions.
Every feature you implement should make the next feature easier to build.