// AUTOMATICALLY enforces world-class software engineering principles for every line of code written. Validates architecture, design patterns, file size limits, code structure, and engineering best practices. USE THIS SKILL AUTOMATICALLY when writing ANY code, creating components, implementing features, or refactoring. Also use when user asks to review architecture, check design patterns, ensure best practices, validate code structure, or improve code quality.
| name | software-principles |
| description | AUTOMATICALLY enforces world-class software engineering principles for every line of code written. Validates architecture, design patterns, file size limits, code structure, and engineering best practices. USE THIS SKILL AUTOMATICALLY when writing ANY code, creating components, implementing features, or refactoring. Also use when user asks to review architecture, check design patterns, ensure best practices, validate code structure, or improve code quality. |
| allowed-tools | ["Read","Grep","Glob"] |
Enforces the foundational principles of world-class software engineering, adapted for the SHEREHE platform built with Next.js 16, React 19, and TypeScript.
This skill MUST be used automatically whenever:
DO NOT wait for the user to ask. Apply these principles proactively.
Activate AUTOMATICALLY when:
"Hide complexity; reveal intent."
Good engineers manage complexity. Great engineers hide it behind clear interfaces.
Server Components (Abstraction Layer)
// โ
GOOD - Abstract data fetching
// app/events/[id]/page.tsx
export default async function EventPage({
params
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params;
const event = await getEvent(id); // Abstracted
return <EventDetails event={event} />;
}
// lib/api/events.ts - Implementation hidden
export async function getEvent(id: string): Promise<Event> {
const response = await fetch(`${API_URL}/events/${id}`, {
next: { revalidate: 3600 }
});
if (!response.ok) throw new EventNotFoundError(id);
return EventSchema.parse(await response.json());
}
Custom Hooks (Abstraction for State Logic)
// โ
GOOD - Abstract complex state logic
// hooks/use-event-form.ts
export function useEventForm(initialData?: Event) {
const [state, setState] = useState<EventFormState>(/* ... */);
const [errors, setErrors] = useState<ValidationErrors>({});
const validate = useCallback((data: EventFormData) => {
return EventFormSchema.safeParse(data);
}, []);
const handleSubmit = useCallback(async (data: EventFormData) => {
const result = validate(data);
if (!result.success) {
setErrors(formatZodErrors(result.error));
return;
}
await saveEvent(result.data);
}, [validate]);
return { state, errors, handleSubmit, validate };
}
// โ
USAGE - Clean, simple API
function CreateEventForm() {
const { state, errors, handleSubmit } = useEventForm();
return <form onSubmit={handleSubmit}>...</form>;
}
โ BAD - Exposed Complexity
// โ BAD - No abstraction, implementation details everywhere
function EventPage() {
const [event, setEvent] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch('/api/events/123')
.then((r) => r.json())
.then(setEvent)
.catch(setError)
.finally(() => setLoading(false));
}, []);
// Component now knows too much about fetching implementation
}
"Divide to conquer."
Split the system into small, self-contained units that evolve independently.
File Structure (Physical Modularity)
app/
โโโ (public)/ # Public pages module
โ โโโ page.tsx
โ โโโ about/page.tsx
โ โโโ early-access/
โ โโโ page.tsx
โ โโโ early-access-client.tsx
โโโ (dashboard)/ # Dashboard module
โ โโโ dashboard/page.tsx
โโโ (events)/ # Events module
โ โโโ events/
โ โโโ [id]/page.tsx
โ โโโ create/page.tsx
components/
โโโ features/ # Feature modules
โ โโโ events/ # Event-specific components
โ โ โโโ EventCard.tsx
โ โ โโโ EventList.tsx
โ โ โโโ EventForm.tsx
โ โโโ auth/ # Auth-specific components
โ โโโ dashboard/ # Dashboard widgets
โโโ ui/ # Base UI module (atoms)
โ โโโ Button.tsx
โ โโโ Input.tsx
โ โโโ Card.tsx
โโโ shared/ # Shared utilities
โโโ FontLoader.tsx
lib/
โโโ api/ # API module
โ โโโ events.ts
โ โโโ users.ts
โ โโโ client.ts
โโโ validations/ # Validation module
โ โโโ event-schema.ts
โ โโโ user-schema.ts
โโโ utils/ # Utility module
Component Modularity (SRP)
// โ
GOOD - Each component does ONE thing
// components/features/events/EventCard.tsx
interface EventCardProps {
event: Event;
onFavorite?: (id: string) => void;
}
export function EventCard({ event, onFavorite }: EventCardProps) {
return (
<div className="card-sherehe">
<EventImage src={event.image} alt={event.name} />
<EventDetails event={event} />
<EventActions eventId={event.id} onFavorite={onFavorite} />
</div>
);
}
// components/features/events/EventImage.tsx
export function EventImage({ src, alt }: EventImageProps) {
return (
<div className="relative h-48 w-full">
<Image
src={src}
alt={alt}
fill
className="object-cover rounded-t-lg"
/>
</div>
);
}
// components/features/events/EventDetails.tsx
export function EventDetails({ event }: { event: Event }) {
return (
<div className="p-4">
<h3 className="font-clash-display text-xl text-sherehe-purple-700">
{event.name}
</h3>
<p className="text-sherehe-purple-600">{formatDate(event.date)}</p>
<p className="text-sm text-sherehe-purple-500">{event.location}</p>
</div>
);
}
โ BAD - God Component (No Modularity)
// โ BAD - One massive component doing everything
function EventPage() {
// 500 lines of code
// Fetching, validation, rendering, state management all mixed
// Hard to test, hard to reuse, hard to maintain
}
lib/, components/ui/, or components/shared/"Don't repeat logic, reuse intelligence."
Write once, use everywhere. Encapsulate patterns into hooks, utilities, and components.
Reusable Hooks
// hooks/use-local-storage.ts
export function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
const [storedValue, setStoredValue] = useState<T>(() => {
if (typeof window === 'undefined') return initialValue;
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch {
return initialValue;
}
});
const setValue = useCallback(
(value: T) => {
try {
setStoredValue(value);
if (typeof window !== 'undefined') {
window.localStorage.setItem(key, JSON.stringify(value));
}
} catch (error) {
console.error(`Error saving to localStorage:`, error);
}
},
[key]
);
return [storedValue, setValue];
}
// โ
USAGE - Reuse everywhere
const [favorites, setFavorites] = useLocalStorage<string[]>('favorites', []);
const [theme, setTheme] = useLocalStorage<Theme>('theme', 'light');
Reusable Utilities
// lib/utils/format.ts
export function formatDate(date: Date | string): string {
const d = typeof date === "string" ? new Date(date) : date;
return new Intl.DateTimeFormat("en-RW", {
year: "numeric",
month: "long",
day: "numeric"
}).format(d);
}
export function formatCurrency(amount: number): string {
return new Intl.NumberFormat("en-RW", {
style: "currency",
currency: "RWF"
}).format(amount);
}
// โ
USAGE - Consistent formatting everywhere
<p>{formatDate(event.date)}</p>
<p>{formatCurrency(event.price)}</p>
Reusable UI Components
// components/ui/Button.tsx
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "outline";
size?: "sm" | "md" | "lg";
isLoading?: boolean;
}
export function Button({
variant = "primary",
size = "md",
isLoading,
children,
...props
}: ButtonProps) {
const baseClass = "btn-base transition-all";
const variantClass = {
primary: "btn-primary",
secondary: "btn-secondary",
outline: "btn-outline"
}[variant];
const sizeClass = {
sm: "text-sm px-3 py-1.5",
md: "text-base px-4 py-2",
lg: "text-lg px-6 py-3"
}[size];
return (
<button
className={`${baseClass} ${variantClass} ${sizeClass}`}
disabled={isLoading}
{...props}
>
{isLoading ? <Spinner /> : children}
</button>
);
}
// โ
USAGE - Consistent buttons everywhere
<Button variant="primary">Submit Event</Button>
<Button variant="outline" size="sm">Cancel</Button>
use-*.ts)lib/utils/ (format, validation, etc.)components/ui/This is not a suggestion. This is a hard constraint that must be enforced on EVERY file.
A file over 500 lines is:
โ GOOD - File under limit
// components/features/events/EventCard.tsx (120 lines)
export function EventCard({ event }: EventCardProps) {
// Clean, focused component
return <div>...</div>;
}
โ ๏ธ WARNING - File approaching limit (450+ lines)
// components/EventManager.tsx (465 lines)
// TIME TO SPLIT! Don't wait until 500.
// Split NOW before it becomes a monster.
โ VIOLATION - File over limit (500+ lines)
// app/dashboard/page.tsx (687 lines) โ REJECTED
// This file is 187 lines over the limit.
// MUST be split into multiple files before merging.
Split by Concern
// Before: UserProfile.tsx (650 lines)
UserProfile.tsx (200 lines) - Main component
UserProfileHeader.tsx (100 lines) - Header section
UserProfileStats.tsx (120 lines) - Stats section
UserProfileActions.tsx (80 lines) - Action buttons
hooks/use-user-data.ts (150 lines) - Data logic
Extract Hooks
// Before: Inline logic (800 lines in component)
// After: Extracted hooks
use-form-validation.ts (150 lines)
use-api-client.ts (120 lines)
use-user-permissions.ts (90 lines)
Component.tsx (180 lines)
Extract Utilities
// Before: Utility functions in component (600 lines)
// After: Separate files
lib/utils/date-format.ts (80 lines)
lib/utils/price-calculations.ts (100 lines)
lib/utils/validation.ts (120 lines)
Component.tsx (200 lines)
Extract Types
// Before: Types + component (550 lines)
// After: Separate type files
types/event.ts (100 lines)
types/user.ts (80 lines)
Component.tsx (220 lines)
Split Components
// Before: Monolith component (800 lines)
// After: Component composition
EventPage.tsx (150 lines) - Container
EventHeader.tsx (80 lines)
EventDetails.tsx (120 lines)
EventActions.tsx (90 lines)
EventComments.tsx (180 lines)
EventGallery.tsx (150 lines)
Before writing code, check:
When reviewing code:
When refactoring:
# Check all files for 500-line violations
find app components lib -name "*.tsx" -o -name "*.ts" | while read file; do
lines=$(wc -l < "$file")
if [ $lines -gt 500 ]; then
echo "โ VIOLATION: $file has $lines lines (limit: 500)"
elif [ $lines -gt 450 ]; then
echo "โ ๏ธ WARNING: $file has $lines lines (approaching limit)"
fi
done
"But this is a configuration file!"
"But this is generated code!"
"But this is a complex form!"
"But this is all related logic!"
Before (720 lines):
app/events/create/page.tsx (720 lines) โ
After (compliant):
app/events/create/
โโโ page.tsx (180 lines) โ
- Server component, metadata
โโโ create-event-client.tsx (220 lines) โ
- Main client component
โโโ components/
โ โโโ EventFormBasics.tsx (150 lines) โ
โ โโโ EventFormDetails.tsx (180 lines) โ
โ โโโ EventFormReview.tsx (120 lines) โ
โ โโโ FormNavigation.tsx (80 lines) โ
โโโ hooks/
โ โโโ use-event-form.ts (200 lines) โ
โโโ validations/
โโโ event-schema.ts (150 lines) โ
"If your file is over 500 lines, you haven't finished your job."
"Each layer handles one concern."
Next.js/React Separation:
// โ
Server Component - Data concern
// app/events/page.tsx
export default async function EventsPage() {
const events = await fetchEvents(); // Server-side data fetching
return <EventsClient events={events} />;
}
// โ
Client Component - Interaction concern
// components/features/events/EventsClient.tsx
'use client';
export function EventsClient({ events }: { events: Event[] }) {
const [filter, setFilter] = useState('all');
const filtered = useFilteredEvents(events, filter);
return (
<>
<FilterControls value={filter} onChange={setFilter} />
<EventGrid events={filtered} />
</>
);
}
// โ
API Route - Backend concern
// app/api/events/route.ts
export async function GET() {
const events = await db.event.findMany();
return Response.json(events);
}
โ Violation:
// โ BAD - Mixing concerns
'use client';
export function EventCard({ eventId }: { eventId: string }) {
const [event, setEvent] = useState(null);
// โ Fetching in client component (should be server)
// โ Styling inline (should be in className)
// โ Validation here (should be in schema)
// โ Business logic mixed with UI
return <div style={{ color: 'blue' }}>...</div>; // โ Inline style
}
types/lib/validations/"One component, one job."
// โ
GOOD - Each does one thing
// Button only handles rendering a button
function Button({ children, onClick }: ButtonProps) {
return <button onClick={onClick}>{children}</button>;
}
// Form only handles form layout
function EventForm({ onSubmit }: EventFormProps) {
return <form onSubmit={onSubmit}>...</form>;
}
// Hook only handles form state
function useEventForm() {
const [data, setData] = useState({});
const [errors, setErrors] = useState({});
return { data, errors, setData };
}
// Utility only formats dates
function formatDate(date: Date): string {
return date.toLocaleDateString();
}
โ Violation:
// โ BAD - Component does too much
function EventManager() {
// Fetching data
// Managing state
// Validating forms
// Rendering UI
// Handling navigation
// Making API calls
// All in one component!
}
"Extract repeated patterns."
// โ BAD - Repeated validation
function CreateEventForm() {
if (!name || name.length < 3) {
/* error */
}
if (!date || new Date(date) < new Date()) {
/* error */
}
}
function EditEventForm() {
if (!name || name.length < 3) {
/* error */
} // Same code!
if (!date || new Date(date) < new Date()) {
/* error */
} // Same code!
}
// โ
GOOD - Extracted validation
// lib/validations/event-schema.ts
export const EventSchema = z.object({
name: z.string().min(3, 'Name must be at least 3 characters'),
date: z.date().min(new Date(), 'Date must be in the future'),
});
// Both forms use the same schema
function CreateEventForm() {
const result = EventSchema.safeParse(data);
}
function EditEventForm() {
const result = EventSchema.safeParse(data);
}
"Simplicity scales. Complexity kills."
// โ
SIMPLE - Easy to understand
function isEventUpcoming(event: Event): boolean {
return new Date(event.date) > new Date();
}
// โ COMPLEX - Over-engineered
function isEventUpcoming(event: Event): boolean {
const now = Date.now();
const eventTime = new Date(event.date).getTime();
const diff = eventTime - now;
const MS_PER_DAY = 1000 * 60 * 60 * 24;
const days = Math.floor(diff / MS_PER_DAY);
return days >= 0;
}
x, tmp, data)"Don't build what's not required today."
// โ BAD - Building for imaginary future
interface Event {
id: string;
name: string;
date: Date;
// Future features we might need...
virtualReality?: boolean;
aiGeneratedContent?: string;
blockchainVerification?: string;
quantumEncryption?: boolean;
}
// โ BAD - Over-abstraction for one use case
class EventManagerFactoryBuilderProvider {
// 500 lines of abstraction for a simple function
}
// โ
GOOD - Build what's needed now
interface Event {
id: string;
name: string;
date: Date;
location: string;
// That's it. Add more when actually needed.
}
"Open for extension, closed for modification."
// โ
GOOD - Extensible via props
interface ButtonProps {
variant?: "primary" | "secondary" | "outline";
size?: "sm" | "md" | "lg";
icon?: React.ReactNode;
onClick?: () => void;
}
// Can extend with new variants without modifying core
<Button variant="primary" icon={<PlusIcon />}>
Create Event
</Button>
"Derived types must be substitutable for their base types."
// โ
GOOD - All input types work the same
interface InputProps {
type: "text" | "email" | "password";
value: string;
onChange: (value: string) => void;
}
// Any Input can be swapped without breaking the form
<Input type="text" value={name} onChange={setName} />
<Input type="email" value={email} onChange={setEmail} />
"Many specific interfaces > One general interface."
// โ
GOOD - Specific interfaces
interface Clickable {
onClick: () => void;
}
interface Hoverable {
onHover: () => void;
}
interface Focusable {
onFocus: () => void;
}
// Components only implement what they need
function Button({ onClick }: Clickable) {}
function Tooltip({ onHover }: Hoverable) {}
"Depend on abstractions, not implementations."
// โ
GOOD - Depends on abstract API client
interface ApiClient {
get<T>(url: string): Promise<T>;
post<T>(url: string, data: unknown): Promise<T>;
}
function useEvents(client: ApiClient) {
return client.get<Event[]>('/events');
}
// Can swap implementations (fetch, axios, mock)
"Validate everything. Trust nothing."
// โ
GOOD - Validate all inputs
import { z } from 'zod';
const EventInputSchema = z.object({
name: z.string().min(1).max(100),
date: z.string().datetime(),
attendees: z.number().int().min(1).max(10000),
});
export async function createEvent(input: unknown) {
// Validate before using
const data = EventInputSchema.parse(input);
// Handle errors
try {
return await db.event.create({ data });
} catch (error) {
if (error instanceof DatabaseError) {
throw new EventCreationError('Failed to save event');
}
throw error;
}
}
"Compose small pieces > Deep hierarchies."
// โ
GOOD - Composition
function Card({ children }: { children: React.ReactNode }) {
return <div className="card-sherehe">{children}</div>;
}
function CardHeader({ children }: { children: React.ReactNode }) {
return <div className="p-4 border-b">{children}</div>;
}
function CardBody({ children }: { children: React.ReactNode }) {
return <div className="p-4">{children}</div>;
}
// Compose them
<Card>
<CardHeader>
<h2>Event Details</h2>
</CardHeader>
<CardBody>
<EventInfo event={event} />
</CardBody>
</Card>
"If it's hard to test, it's badly designed."
// โ
GOOD - Pure function, easy to test
export function calculateEventPrice(
basePrice: number,
attendees: number,
discount: number
): number {
return basePrice * attendees * (1 - discount);
}
// Test:
expect(calculateEventPrice(100, 10, 0.1)).toBe(900);
// โ
GOOD - Component with clear inputs/outputs
export function EventCard({ event, onSelect }: EventCardProps) {
return (
<div onClick={() => onSelect(event.id)}>
<h3>{event.name}</h3>
</div>
);
}
// Test: Render with mock data, verify onClick
"Automate everything repeated."
// package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"type-check": "tsc --noEmit",
"format": "prettier --write .",
"test": "jest",
"test:watch": "jest --watch",
"pre-commit": "lint-staged",
"prepare": "husky install"
}
}
"Document the 'why', not the 'what'."
/**
* Calculates the total event cost including all fees and taxes.
*
* @param basePrice - Base price per attendee in RWF
* @param attendees - Number of expected attendees
* @param serviceType - Type of service (determines fee structure)
* @returns Total cost in RWF
*
* @example
* calculateTotalCost(50000, 100, "premium")
* // Returns 5500000 (base + 10% premium fee)
*
* @remarks
* Premium services include venue decoration and catering.
* Standard services are venue rental only.
* Fee structures are defined in PRICING.md
*/
export function calculateTotalCost(
basePrice: number,
attendees: number,
serviceType: ServiceType
): number {
// Implementation
}
"Fast code is good code."
// โ
Server Component - No JS to client
export default async function EventsPage() {
const events = await fetchEvents();
return <EventsList events={events} />;
}
// โ
Memoization for expensive calculations
const sortedEvents = useMemo(
() => events.sort((a, b) => a.date.getTime() - b.date.getTime()),
[events]
);
// โ
Dynamic imports for heavy components
const HeavyChart = dynamic(() => import('@/components/HeavyChart'), {
loading: () => <Skeleton />,
ssr: false
});
// โ
Image optimization
<Image
src={event.image}
alt={event.name}
width={800}
height={600}
priority={isAboveFold}
/>
When activated, follow this process:
Identify Scope
Read & Analyze
Check Principles (in priority order)
Provide Recommendations
## Architecture Review Results
### Files Reviewed (with line counts)
- app/events/page.tsx (324 lines) โ
- components/features/events/EventCard.tsx (120 lines) โ
- app/early-access/early-access-client.tsx (265 lines) โ
- lib/api/events.ts (89 lines) โ
### ๐จ 500-Line Limit Check
- โ
All files under 500-line limit
- โ ๏ธ No files in warning zone (450-500 lines)
- โ
PASS
### โ
Strengths
1. **File Size Compliance** - All files well under 500-line limit
2. **Separation of Concerns** - Server/Client split is clean
3. **SHEREHE Brand Compliance** - All colors use design system
4. **TypeScript Safety** - No `any` types
### โ ๏ธ Issues Found
#### ๐ด CRITICAL: Violation of DRY Principle
**File**: `components/features/events/EventCard.tsx:45`
**Issue**: Duplicate date formatting logic
**Current Code**:
```typescript
const formatted = new Date(event.date).toLocaleDateString();
```
Found in: 5 different components
Recommendation: Extract to utility
// lib/utils/format.ts
export function formatEventDate(date: Date): string {
return new Intl.DateTimeFormat('en-RW', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(date);
}
File: app/events/page.tsx:20-150
Issue: Component is 130 lines, doing too much
Recommendation: Split into:
EventsPage (server, data fetching)EventsClient (client, interactions)EventFilters (filtering logic)EventGrid (rendering)โ ๏ธ NEEDS REFACTORING - Address critical issues before production
---
### Example 2: 500-Line Violation (Instant Rejection)
```markdown
## Architecture Review Results
### Files Reviewed (with line counts)
- app/dashboard/page.tsx (687 lines) โ VIOLATION
- components/UserDashboard.tsx (523 lines) โ VIOLATION
- hooks/use-dashboard-data.ts (456 lines) โ ๏ธ WARNING ZONE
- lib/api/dashboard.ts (342 lines) โ
### ๐จ 500-Line Limit Check
โ **CRITICAL VIOLATIONS FOUND**
#### โ VIOLATION #1: app/dashboard/page.tsx
- **Current**: 687 lines
- **Limit**: 500 lines
- **Overage**: 187 lines (37% over limit)
- **Status**: ๐จ **INSTANT REJECTION**
**Required Action**: MUST split before proceeding
**Suggested Split**:
app/dashboard/ โโโ page.tsx (180 lines) - Server component โโโ dashboard-client.tsx (220 lines) - Client wrapper โโโ components/ โ โโโ DashboardHeader.tsx (120 lines) โ โโโ DashboardStats.tsx (150 lines) โ โโโ RecentActivity.tsx (180 lines) โ โโโ QuickActions.tsx (100 lines) โโโ hooks/ โโโ use-dashboard.ts (200 lines)
#### โ VIOLATION #2: components/UserDashboard.tsx
- **Current**: 523 lines
- **Limit**: 500 lines
- **Overage**: 23 lines (5% over limit)
- **Status**: ๐จ **INSTANT REJECTION**
**Required Action**: Extract 50+ lines minimum
**Suggested Fix**:
- Extract profile section โ UserProfile.tsx (150 lines)
- Extract settings panel โ UserSettings.tsx (120 lines)
- Keep main layout โ UserDashboard.tsx (250 lines)
#### โ ๏ธ WARNING: hooks/use-dashboard-data.ts
- **Current**: 456 lines
- **Limit**: 500 lines
- **Remaining**: 44 lines
- **Status**: โ ๏ธ **WARNING ZONE (450-500)**
**Recommendation**: Split NOW before reaching limit
**Suggested Split**:
- use-dashboard-stats.ts (180 lines)
- use-dashboard-activities.ts (150 lines)
- use-dashboard-actions.ts (120 lines)
### ๐ REVIEW STOPPED
**Cannot proceed with architectural review while 500-line violations exist.**
This code is **NOT PRODUCTION READY** and must be refactored before:
- Further development
- Code review
- Testing
- Deployment
### Required Next Steps
1. **IMMEDIATELY**: Stop all feature development
2. **FIRST**: Split violating files (app/dashboard/page.tsx, UserDashboard.tsx)
3. **SECOND**: Split warning-zone files (use-dashboard-data.ts)
4. **THIRD**: Request new review after refactoring
5. **ONLY THEN**: Continue with feature development
### Final Verdict
โ **REJECTED - 500-Line Violations**
**Files must be split before any other work proceeds.**
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." โ Martin Fowler
These principles aren't rules to follow blindly. They're tools to help you write:
any or unknown - TypeScript strict modeThis skill activates automatically when writing code. You don't need to ask.
Every time you write a component, hook, or utility:
The 500-line rule is not optional. It's fundamental to writing maintainable software.