frontend-architecture
Skill6 starsChanged 2 months agoApache-2.0View on GitHub
Defines a Clean Architecture and reusable component structures for frontend. Especially useful when the user wants to organize pages, tables, lists, item cards, subpages, and modal dialogs in a predictable and maintainable way. Applies to React, Vue, Svelte, or similar frameworks.
15 other projects use a version of this.
Adopted by
Most recently taken up by
- veegres/ivorytheir own version, first seen Nov 9, 2026
- harshitsinghbhandari/domain-expansiontheir own version, first seen Nov 8, 2026
- DnsQueen/orcinus-skillstheir own version, first seen Nov 8, 2026
- SWEStash/swe-workflow-skillstheir own version, first seen Nov 8, 2026
- hushh-labs/hushh-researchtheir own version, first seen Nov 1, 2026
- nimadorostkar/Claude-Skills-collectiontheir own version, first seen Oct 13, 2026
Used with
Projects with it also use backend-architecture, mobile-design and 5 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoldenWing-360Skillbackend-architecture
Design backends that survive redeploys, server reboots, and modest scaling. Covers stateless application servers, state placement (object storage, managed databases, Redis), immutable deploy artifacts, health checks, graceful shutdown, database migrations that don't lock the world, and the twelve-factor baseline. Invoke when designing a new backend, when uploads disappear after a redeploy, or when productionizing a vibe-coded prototype.
Also in 3 projects that use this
xenitV1Skillmobile-design
Mobile-first design thinking and decision-making for iOS and Android apps. Touch interaction, performance patterns, platform conventions. Teaches principles, not fixed values. Use when building React Native, Flutter, or native mobile apps.
Also in 3 projects that use this
harrissohail6Skilldatabase-design
Database schema design and SQL best practices. Use when designing tables, writing queries, or optimizing database performance.
Also in 3 projects that use this
xenitV1Skillclean-code
Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments
Also in 3 projects that use this
AnthropicSkillarchitecture
Create or evaluate an architecture decision record (ADR). Use when choosing between technologies (e.g., Kafka vs SQS), documenting a design decision with trade-offs and consequences, reviewing a system design proposal, or designing a new component from requirements and constraints.
Also in 3 projects that use this
JetBrainsSkillwebapp-testing
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Also in 3 projects that use this
Other versions15 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 15
- vudovn/ag-kit★ 8.2ksame name
- vudovn/antigravity-kit★ 8.2ksame name
- veegres/ivory★ 282same name
- hushh-labs/hushh-research★ 40same name
- nimadorostkar/Claude-Skills-collection★ 33same name
- microsoft/FSQ★ 23same name
- stareezy-1/frontend-architecture-skill★ 10same name
- harshitsinghbhandari/domain-expansion★ 2same name
- we-are-singular/skills★ 2same name
- yend724/agent-skills★ 2same name
5 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository22 other files it gives its agents.
- backend-api-standardsSkill
- brain-orchestratorSkill
- brand-guidelinesSkill
- code-architecture-explainerSkill
- code-documentationSkill
- create-pull-requestSkill
- frontend-designSkill
- gh-stackSkill
- git-commitsSkill
- latex-academic-reportsSkill
- pre-pr-reviewSkill
- project-intelligenceSkill
- project-setupSkill
- spec-kit-amend-artifactsSkill
- spec-kit-analyze-consistencySkill
- spec-kit-establish-constitutionSkill
- spec-kit-execute-tasksSkill
- spec-kit-generate-planSkill
- spec-kit-generate-specSkill
- spec-kit-generate-tasksSkill
- spec-kit-sync-artifactsSkill
- verify-before-implementSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. 0 are common, 10 are distinctive, and 6 are very specific to this project.
0
Common
Most of the 13 edited versions we read keep these.
10
Distinctive
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
When starting a new frontend project with professional structure
- Distinctive: line 14
When the user mentions "clean architecture", "layers", "use cases"
- Distinctive: line 15
If the project requires screens with lists, tables, cards, subpages, and modal dialogs
- Distinctive: line 91
All pages and their subcomponents must follow this structure:
- Distinctive: line 95
Every screen follows this strict composition order:
- Very specific: line 110
Buttons: never contain logic; they only open a Dialog, navigate, or mount another module's component.
- Distinctive: line 117
If a Dialog already exists for a given purpose (e.g.: a confirmation dialog, a generic form dialog, an entity create/edit dialog), reuse it …
- Very specific: line 120
Before creating a Dialog, check if an equivalent one already exists in the module's components/ or in presentation/shared/components/.
- Very specific: line 122
If the same Dialog is needed by more than one module, promote it to presentation/shared/components/ and import it from there.
- Distinctive: line 176
Every table or list must be an independent component.
- Distinctive: line 221
If a list with cards is used instead of a table, each item goes in its own component.
- Very specific: line 238
If a page has a subpage (e.g.: ProductDetailPage inside the products module), it follows the same pattern: it's called Page, is composed of …
- Distinctive: line 366
Subpages: follow exactly the same pattern as main pages.
- Very specific: line 367
Every creation/editing form: must go inside a Dialog.
- Very specific: line 374
Never duplicate a Dialog: if an equivalent Dialog already exists, reuse it.
- Distinctive: line 378
When the user asks to create a new page, automatically generate:
“Common” is measured: kept by at least 6 in 10 of the 13 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Frontend Architecture Skill
This skill establishes a standard architecture and a component pattern for frontend, based on Clean Architecture. Its goal is to guarantee consistency, maintainability, and separation of concerns in projects of any size.
When to use this skill?
- When starting a new frontend project with professional structure
- When the user mentions "clean architecture", "layers", "use cases"
- If the project requires screens with lists, tables, cards, subpages, and modal dialogs
- To maintain a consistent pattern across pages and components
Clean Architecture in Frontend (Summary)
The architecture is organized in concentric layers, where dependencies point inward:
presentation layer (UI)
↓
use cases layer (business logic)
↓
repositories layer (abstractions)
↓
entities layer (domain models)Recommended folder structure (React example):
src/
├── domain/ # Innermost layer: entities
│ ├── entities/ # models (e.g.: Product, User)
│ └── repositories/ # repository interfaces (e.g.: IProductRepository)
├── application/ # use cases (grouped by module when many)
│ └── useCases/
│ ├── products/
│ │ ├── GetProductsUseCase.ts
│ │ ├── CreateProductUseCase.ts
│ │ └── DeleteProductUseCase.ts
│ └── users/
│ ├── GetUsersUseCase.ts
│ └── CreateUserUseCase.ts
├── infrastructure/ # concrete repository implementations
│ └── repositories/ # (e.g.: ApiProductRepository, LocalStorageRepository)
├── presentation/ # outer layer: modules organized by feature
│ ├── products/
│ │ ├── ProductsPage.tsx
│ │ └── components/
│ │ ├── ProductsTable.tsx
│ │ ├── ProductCard.tsx
│ │ └── CreateProductDialog.tsx
│ ├── users/
│ │ ├── UsersPage.tsx
│ │ └── components/
│ │ ├── UsersTable.tsx
│ │ └── CreateUserDialog.tsx
│ ├── components/ # UI library components (e.g.: shadcn/ui)
│ │ └── ui/ # shadcn generated components (button, dialog, table, ...)
│ ├── lib/ # UI library helpers (e.g.: shadcn's utils.ts -> cn())
│ │ └── utils.ts
│ ├── shared/ # shared components across modules
│ │ └── components/
│ ├── hooks/ # hooks grouped by module when many
│ │ ├── products/
│ │ │ └── useProducts.ts
│ │ └── users/
│ │ └── useUsers.ts
│ └── contexts/ # if applicable
└── config/ # global configurationsUI library rule (shadcn, etc.): Any UI/component library that scaffolds its own folders (such as shadcn/ui) must live inside
presentation/, never at the root ofsrc/. This includes its components (presentation/components/ui/), itslib/helpers (e.g.:presentation/lib/utils.tswith thecn()function), and any other generated assets (styles, providers, config helpers). The reason: these are pure presentation concerns and must not leak intodomain/,application/, orinfrastructure/. Configure the library so its aliases point intopresentation/(e.g.: incomponents.jsonset"aliases.components": "@/presentation/components"and"aliases.utils": "@/presentation/lib/utils").
Rule: When a module grows in complexity (many use cases, hooks, components, repositories, etc.), all related files must be grouped in their own subfolder named after the module. This applies to any layer:
useCases/products/,hooks/products/,repositories/products/, etc. Keep everything organized by module to maintain clarity at scale.
Mandatory Component Pattern
All pages and their subcomponents must follow this structure:
Standard composition hierarchy
Every screen follows this strict composition order:
Page
└─ Main component (Table / List / Cards) ← the primary content of the route
└─ Action buttons ← buttons that trigger secondary UI
├─ open Dialogs (create / edit / confirm)
└─ navigate to / mount other modules
└─ Other components (Dialogs, panels, drawers, ...)Rules of the hierarchy:
- A Page orchestrates: it renders one main component (the table, list, or card grid) plus the buttons that open everything else.
- Buttons never contain logic; they only open a
Dialog, navigate, or mount another module's component. - Everything a button opens (Dialogs, drawers, secondary modules) is a separate component, composed by the Page, never inlined.
Reuse Dialogs — never duplicate
If a Dialog already exists for a given purpose (e.g.: a confirmation dialog, a generic form dialog, an entity create/edit dialog), reuse it instead of creating a new one.
- Before creating a Dialog, check if an equivalent one already exists in the module's
components/or inpresentation/shared/components/. - If the same Dialog is needed by more than one module, promote it to
presentation/shared/components/and import it from there. - Generic, repeated dialogs (e.g.:
ConfirmDialog,FormDialog) must be parameterized via props (title, fields, callbacks) so a single component covers every case instead of duplicating near-identical dialogs. - Duplicating a Dialog that already exists is not allowed.
1. Page (main page)
A page is a component that contains the complete structure of a route. It never contains domain logic, only use case orchestration and composition of child components.
React example:
// presentation/products/ProductsPage.tsx
import { useProducts } from "../hooks/products/useProducts";
import { ProductsTable } from "./components/ProductsTable";
import { CreateProductDialog } from "./components/CreateProductDialog";
import { useState } from "react";
export function ProductsPage() {
const { products, loading, addProduct, deleteProduct } = useProducts();
const [isDialogOpen, setIsDialogOpen] = useState(false);
return (
<div className="p-6">
<div className="flex justify-between items-center mb-4">
<h1 className="text-2xl font-bold">Products</h1>
<button
onClick={() => setIsDialogOpen(true)}
className="bg-blue-600 text-white px-4 py-2 rounded"
>
+ Add product
</button>
</div>
{loading ? (
<div>Loading...</div>
) : (
<ProductsTable products={products} onDelete={deleteProduct} />
)}
<CreateProductDialog
open={isDialogOpen}
onClose={() => setIsDialogOpen(false)}
onSave={addProduct}
/>
</div>
);
}2. Tables / Lists (separate component)
Every table or list must be an independent component. It receives data and callbacks as props. It never fetches directly.
Example:
// presentation/products/components/ProductsTable.tsx
interface Product {
id: string;
name: string;
price: number;
}
interface Props {
products: Product[];
onDelete: (id: string) => void;
}
export function ProductsTable({ products, onDelete }: Props) {
return (
<table className="w-full border">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{products.map((p) => (
<tr key={p.id}>
<td>{p.name}</td>
<td>{p.price}</td>
<td>
<button onClick={() => onDelete(p.id)}>Delete</button>
</td>
</tr>
))}
</tbody>
</table>
);
}3. Item Card / List item
If a list with cards is used instead of a table, each item goes in its own component.
// presentation/products/components/ProductCard.tsx
export function ProductCard({ product, onDelete }: Props) {
return (
<div className="border rounded p-4 shadow">
<h3>{product.name}</h3>
<p>${product.price}</p>
<button onClick={() => onDelete(product.id)}>Delete</button>
</div>
);
}4. Subpages
If a page has a subpage (e.g.: ProductDetailPage inside the products module), it follows the same pattern: it's called Page, is composed of components (tables, cards, dialogs), and is placed inside its module folder.
Example:
// presentation/products/ProductDetailPage.tsx
export function ProductDetailPage() {
return (
<div>
<h1>Product Detail</h1>
<ProductInfo />
<RelatedProductsList />
</div>
);
}5. Always use Dialogs (modals)
Any creation or editing form must go inside a Dialog (modal). The dialog is an independent component that receives open, onClose, onSave.
Example:
// presentation/products/components/CreateProductDialog.tsx
interface Props {
open: boolean;
onClose: () => void;
onSave: (product: Omit<Product, "id">) => void;
}
export function CreateProductDialog({ open, onClose, onSave }: Props) {
const [name, setName] = useState("");
const [price, setPrice] = useState(0);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSave({ name, price });
onClose();
setName("");
setPrice(0);
};
if (!open) return null;
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center">
<div className="bg-white p-6 rounded-lg w-96">
<h2>Create Product</h2>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full border p-2 mb-2"
/>
<input
type="number"
placeholder="Price"
value={price}
onChange={(e) => setPrice(Number(e.target.value))}
className="w-full border p-2 mb-4"
/>
<div className="flex justify-end gap-2">
<button type="button" onClick={onClose}>
Cancel
</button>
<button
type="submit"
className="bg-blue-600 text-white px-4 py-2 rounded"
>
Save
</button>
</div>
</form>
</div>
</div>
);
}Hook to orchestrate use cases (optional but recommended)
Hooks act as a bridge between the UI and use cases. They contain state and call use cases.
// presentation/hooks/products/useProducts.ts
import { useEffect, useState } from "react";
import { GetProductsUseCase } from "../../../application/useCases/products/GetProductsUseCase";
import { CreateProductUseCase } from "../../../application/useCases/products/CreateProductUseCase";
import { DeleteProductUseCase } from "../../../application/useCases/products/DeleteProductUseCase";
import { Product } from "../../domain/entities/Product";
export function useProducts() {
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(true);
const getProductsUseCase = new GetProductsUseCase(/* repository */);
const createProductUseCase = new CreateProductUseCase(/* repository */);
const deleteProductUseCase = new DeleteProductUseCase(/* repository */);
useEffect(() => {
getProductsUseCase
.execute()
.then(setProducts)
.finally(() => setLoading(false));
}, []);
const addProduct = async (product: Omit<Product, "id">) => {
const newProduct = await createProductUseCase.execute(product);
setProducts((prev) => [...prev, newProduct]);
};
const deleteProduct = async (id: string) => {
await deleteProductUseCase.execute(id);
setProducts((prev) => prev.filter((p) => p.id !== id));
};
return { products, loading, addProduct, deleteProduct };
}Non-negotiable Rules
- Pages NEVER contain domain logic or direct fetch.
- Tables/lists are separate components, they receive data via props.
- Item cards are also separate components.
- Subpages follow exactly the same pattern as main pages.
- Every creation/editing form must go inside a
Dialog. - Use cases are classes or pure functions that don't depend on the UI.
- Repositories are injected into use cases (dependency inversion).
- Each module has its own folder with its page and a
components/subfolder. - When a module grows, all its related files (use cases, hooks, repositories, components, etc.) must be grouped in subfolders named after the module across all layers.
- UI libraries (shadcn/ui, etc.) and everything they generate — components (
components/ui/), theirlib/helpers (utils.ts/cn()), styles and config helpers — always live insidepresentation/, never at the root ofsrc/nor indomain/,application/, orinfrastructure/. - Composition hierarchy is fixed:
Page → main component (Table/List/Cards) + buttons → the Dialogs / modules those buttons open. Buttons only open Dialogs, navigate, or mount other modules; they hold no logic. - Never duplicate a Dialog: if an equivalent Dialog already exists, reuse it. Shared dialogs go in
presentation/shared/components/and generic ones (ConfirmDialog,FormDialog) are parameterized via props.
Quick Template for New Pages
When the user asks to create a new page, automatically generate:
presentation/{module}/{Module}Page.tsx(with layout, title, add button, and hook usage)presentation/{module}/components/{Module}Table.tsxor{Module}List.tsxpresentation/{module}/components/{Module}Dialog.tsx(for create/edit)presentation/hooks/use{Module}.ts(with corresponding use cases)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

