atomic-design
Build Web Components
Reuse-First Rule
Treat raw DOM or HTML elements, or equivalent low-level primitives, as implementation details of reusable building blocks instead of the default way to assemble feature UI.
Follow this order every time:
- Reuse an existing generic component.
- Generalize an existing non-generic component and reuse it.
- Write new code only after exhausting 1 and 2.
- Extract smaller reusable pieces from the new code immediately.
Aim for feature components to be composed mostly of project components, design-system primitives, and framework-native composition mechanisms. Keep direct low-level nodes isolated inside reusable primitives whenever practical.
Workflow
-
Detect the stack and local component model.
- Identify the framework, styling approach, and design-system packages already in use.
- Read nearby components before editing.
- Load references/reuse-checklist.md for search heuristics, stack mappings, and extraction signals.
-
Search for reusable generic components first.
- Search by behavior, structure, and visual role, not only by name.
- Inspect shared component folders, design-system packages, feature libraries, and existing UI kits.
- Prefer existing slots, variants, composition props, render props, and style tokens over copy-paste.
- Avoid adding a new UI library unless the task explicitly requires it.
-
Search for a component that can be generalized if no generic component fits.
- Look for the same layout skeleton or interaction model with feature-specific copy, icons, data, or styling.
- Extract hard-coded content into props, slots, children, variants, or configuration.
- Preserve current behavior for existing callers unless the task explicitly allows a breaking cleanup.
- Reuse the generalized version instead of duplicating the original markup.
-
Write new code only after exhausting reuse and generalization.
- Start with the smallest reusable boundary that can solve the task.
- Introduce new primitives in the design-system or shared layer when the abstraction is broadly useful.
- Keep raw platform nodes inside those primitives instead of spreading them across higher-level feature components.
-
Extract reusable subcomponents immediately after writing new code.
- Extract repeated or clearly named markup clusters in the same task.
- Prefer local feature-shared components first. Promote to global shared components only after the abstraction proves useful beyond one feature area.
-
Keep the final component tree high-level.
- Make feature components read like product intent, not like DOM assembly.
- Treat many direct low-level elements in a feature component as a smell and refactor further unless the structure is truly unique or semantically required.
Generalize Safely
Generalize only when the abstraction has a stable shape.
- Extract variable content, actions, media, adornments, and state into props or slots.
- Rename components to domain-neutral names when they should escape their original feature.
- Prefer backward-compatible migration paths such as wrappers, aliases, or default props.
- Avoid speculative abstractions that do not have a clear second use case.
Keep Raw Elements Contained
Treat this as the default quality bar instead of a literal hard limit:
- Keep near-zero raw HTML elements or equivalent low-level primitives in feature, page, and section components.
- Allow raw elements inside shared primitives because someone must encapsulate the platform.
- Use raw elements directly only for semantics that must stay explicit, framework constraints, tiny leaf wrappers, or brand-new primitives being extracted in the same task.
- Cluster any unavoidable low-level markup in a small number of reusable files.
Report the Outcome
When finishing the task:
- State which existing components were reused.
- State which components were generalized and how.
- State which new reusable pieces were extracted if new code was required.
- State which raw low-level elements remain and why they could not be abstracted further.
More from code-sherpas/agent-skills
neverthrow-return-types
Require `neverthrow`-based return types in TypeScript and JavaScript code whenever the surrounding technology allows it. Use when creating, refactoring, reviewing, or extending standalone functions, exported module functions, class methods, object methods, service methods, repository methods, and similar APIs that should expose explicit success and failure result types in their signatures. Prefer `Result<T, E>` for synchronous code and `ResultAsync<T, E>` for asynchronous code. Only skip a `neverthrow` return type when a framework, library, runtime interface, or externally imposed contract is incompatible and requires a different return shape.
16write-persistence-representations
Create or update persistence-layer data representations in any stack, including ORM entities, schema definitions, table mappings, document models, collection definitions, and similar database-facing code. Use when agents needs to add or change persisted fields, identifiers, relationships, indexes, timestamps, auditing fields, or storage mappings in frameworks, libraries, or ORMs such as Prisma, TypeORM, Sequelize, Drizzle, Mongoose, Hibernate/JPA, Doctrine, Ecto, Active Record, or equivalent persistence technologies.
7business-logic
Identify, interpret, review, or write business logic in code. Use when an agent needs to decide whether code expresses business rules, business algorithms, or business workflows, or when it must implement, preserve, or refactor code that creates, stores, or transforms data according to real business policies.
7immutable-domain-entities
Require the immutable design pattern for domain entities. Use when an agent needs to create, modify, review, or interpret domain entities and should preserve identity while expressing state changes through new immutable instances. Domain entities must be modeled as immutable classes, not as plain type aliases or interfaces paired with standalone functions.
7update-agent-skills
Update agent skills installed with the `skills` CLI. Use when asked to refresh installed skills, keep a project's skills current, or troubleshoot cases where `npx skills update` reports that everything is up to date. For project-scoped installs, a no-change update must immediately run the bundled reinstall script so tracked skills from `skills-lock.json` are reinstalled without extra investigation.
7business-logic-entry-point-repository-operations
Require repository interfaces to expose a standard set of operations with specific signatures and naming conventions. Use when an agent needs to create, modify, review, or interpret repository interfaces used by business-logic entry points. Repositories must offer findById (fails when entity is absent — never returns null or optional), create (returns created entity), update (returns updated entity), search (returns collection), and deleteById (returns nothing). Do not use a generic "save" operation — always distinguish between create and update explicitly.
6