Frontend Architecture
Component architecture, design patterns, state management strategies, module systems, build tools, and scalable application structure
Specification
- Skill ID
- manutej/luxor-claude-marketplace/frontend-architecture
- Publisher
- manutej
- Repository
- luxor-claude-marketplace
- Installs
- 0
- Files
- 3
- Synced
- Sep 23, 2026
How to use it
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
manutej/luxor-claude-marketplace/frontend-architectureInstalls these files- EXAMPLES.md
- README.md
- SKILL.md
What this skill tells the agent
Frontend Architecture Skill
When to Use This Skill
Use this skill when you need to:
- Design scalable application architecture - Structure large-scale frontend applications with maintainable patterns
- Choose architectural patterns - Select appropriate design patterns (MVC, MVVM, Flux) for your use case
- Implement state management - Design state architecture for complex applications
- Structure component hierarchies - Create reusable, composable component systems
- Optimize build processes - Configure bundlers and build tools for optimal performance
- Plan testing strategies - Architect comprehensive testing approaches across layers
- Design module systems - Implement code splitting, lazy loading, and module boundaries
- Scale codebases - Establish conventions for growing teams and applications
- Refactor legacy code - Migrate to modern architectural patterns
- Performance optimization - Structure applications for optimal load times and runtime performance
Core Concepts
1. Component Architecture
Component-based architecture is the foundation of modern frontend development, enabling modularity and reusability.
Component Design Principles
Single Responsibility Principle Each component should have one clear purpose:
// Bad: Component doing too much
function UserDashboard() {
const [user, setUser] = useState(null);
const [posts, setPosts] = useState([]);
const [notifications, setNotifications] = useState([]);
const [settings, setSettings] = useState({});
// Mixing concerns: data fetching, rendering, business logic
useEffect(() => {
fetch('/api/user').then(r => r.json()).then(setUser);
fetch('/api/posts').then(r => r.json()).then(setPosts);
fetch('/api/notifications').then(r => r.json()).then(setNotifications);
}, []);
return (
<div>
<header>{user?.name}</header>
<PostList posts={posts} />
<NotificationBell count={notifications.length} />
<SettingsPanel settings={settings} />
</div>
);
}
// Good: Separated concerns
function UserDashboard() {
return (
<DashboardLayout>
<UserHeader />
<UserPosts />
<UserNotifications />
<UserSettings />
</DashboardLayout>
);
}
function UserPosts() {
const { posts, loading } = useUserPosts();
if (loading) return <PostsLoading />;
return <PostList posts={posts} />;
}Composition Over Inheritance
// Using composition for flexibility
interface ButtonProps {
children: React.ReactNode;
onClick?: () => void;
variant?: 'primary' | 'secondary';
}
function Button({ children, onClick, variant = 'primary' }: ButtonProps) {
return (
<button className={`btn btn-${variant}`} onClick={onClick}>
{children}
</button>
);
}
// Compose complex components
function IconButton({ icon, ...props }: ButtonProps & { icon: string }) {
return (
<Button {...props}>
<Icon name={icon} />
{props.children}
</Button>
);
}
function LoadingButton({ loading, ...props }: ButtonProps & { loading: boolean }) {
return (
<Button {...props} disabled={loading}>
{loading ? <Spinner /> : props.children}
</Button>
);
}Container vs Presentational Components
// Presentational Component (Pure UI)
interface UserCardProps {
user: User;
onEdit: () => void;
onDelete: () => void;
}
function UserCard({ user, onEdit, onDelete }: UserCardProps) {
return (
<div className="user-card">
<img src={user.avatar} alt={user.name} />
<h3>{user.name}</h3>
<p>{user.email}</p>
<div className="actions">
<button onClick={onEdit}>Edit</button>
<button onClick={onDelete}>Delete</button>
</div>
</div>
);
}
// Container Component (Logic & Data)
function UserCardContainer({ userId }: { userId: string }) {
const { data: user, isLoading } = useQuery(['user', userId], () =>
fetchUser(userId)
);
const deleteMutation = useMutation(deleteUser);
const navigate = useNavigate();
const handleEdit = () => navigate(`/users/${userId}/edit`);
const handleDelete = () => {
if (confirm('Delete user?')) {
deleteMutation.mutate(userId);
}
};
if (isLoading) return <Skeleton />;
if (!user) return <ErrorState />;
return (
<UserCard
user={user}
onEdit={handleEdit}
onDelete={handleDelete}
/>
);
}2. Separation of Concerns
Layer Architecture
┌─────────────────────────────────────┐
│ Presentation Layer │
│ (Components, Views, UI) │
├─────────────────────────────────────┤
│ Application Layer │
│ (State Management, Routing, Hooks) │
├─────────────────────────────────────┤
│ Domain Layer │
│ (Business Logic, Entities) │
├─────────────────────────────────────┤
│ Infrastructure Layer │
│ (API, Storage, Services) │
└─────────────────────────────────────┘Example Implementation:
// Domain Layer - Business entities and logic
export class User {
constructor(
public id: string,
public email: string,
public name: string,
public role: UserRole
) {}
canEditPost(post: Post): boolean {
return this.role === 'admin' || post.authorId === this.id;
}
get displayName(): string {
return this.name || this.email.split('@')[0];
}
}
// Infrastructure Layer - API communication
export class UserRepository {
constructor(private apiClient: ApiClient) {}
async findById(id: string): Promise<User> {
const data = await this.apiClient.get(`/users/${id}`);
return new User(data.id, data.email, data.name, data.role);
}
async save(user: User): Promise<void> {
await this.apiClient.put(`/users/${user.id}`, {
email: user.email,
name: user.name,
role: user.role
});
}
}
// Application Layer - State management
export function useUser(userId: string) {
const repository = useUserRepository();
return useQuery({
queryKey: ['user', userId],
queryFn: () => repository.findById(userId)
});
}
// Presentation Layer - UI Component
export function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading } = useUser(userId);
if (isLoading) return <Loading />;
return (
<div>
<h1>{user.displayName}</h1>
<p>{user.email}</p>
</div>
);
}Design Patterns
1. Model-View-Controller (MVC)
// Model - Data and business logic
class TodoModel {
private todos: Todo[] = [];
private observers: Set<(todos: Todo[]) => void> = new Set();
addTodo(text: string) {
const todo = { id: Date.now(), text, completed: false };
this.todos.push(todo);
this.notify();
}
toggleTodo(id: number) {
const todo = this.todos.find(t => t.id === id);
if (todo) {
todo.completed = !todo.completed;
this.notify();
}
}
getTodos() {
return [...this.todos];
}
subscribe(observer: (todos: Todo[]) => void) {
this.observers.add(observer);
return () => this.observers.delete(observer);
}
private notify() {
this.observers.forEach(observer => observer(this.getTodos()));
}
}
// Controller - Handles user input
class TodoController {
constructor(private model: TodoModel) {}
handleAddTodo(text: string) {
if (text.trim()) {
this.model.addTodo(text);
}
}
handleToggleTodo(id: number) {
this.model.toggleTodo(id);
}
}
// View - React component
function TodoView() {
const [model] = useState(() => new TodoModel());
const [controller] = useState(() => new TodoController(model));
const [todos, setTodos] = useState(model.getTodos());
const [inputValue, setInputValue] = useState('');
useEffect(() => {
return model.subscribe(setTodos);
}, [model]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
controller.handleAddTodo(inputValue);More from manutej
Use this skill in a project
Open any RiverX project, search the Skills panel for manutej/luxor-claude-marketplace/frontend-architecture, and install it in one click.
