projectrules.ai

Shadcn UI Best Practices

shadcnuibest-practicesreacttailwind

Description

This rule provides comprehensive best practices for developing with Shadcn UI, covering code organization, performance, security, and testing.

Globs

**/*.{js,jsx,ts,tsx}
---
description: This rule provides comprehensive best practices for developing with Shadcn UI, covering code organization, performance, security, and testing.
globs: **/*.{js,jsx,ts,tsx}
---

# Shadcn UI Best Practices

This document outlines best practices for developing with Shadcn UI, covering code organization, common patterns, performance considerations, security, testing, common pitfalls, and tooling.

## 1. Code Organization and Structure

- **Directory Structure:**
    - Organize components into logical directories based on functionality or domain. For example, place form-related components in a `components/forms` directory.
    - Separate components into their own files.  Each component should have a dedicated file named after the component (e.g., `Button.tsx`).
    - Consider using an `index.ts` file within each directory to export all components from that directory, simplifying imports.
    - Structure directories to reflect the UI hierarchy.  For example, `/components/layout` for layout related components and `/components/ui` for reusable UI elements.

- **File Naming Conventions:**
    - Use PascalCase for component file names (e.g., `MyComponent.tsx`).
    - Use camelCase for variable and function names (e.g., `handleClick`).
    - Use descriptive names that clearly indicate the purpose of the component or function.

- **Module Organization:**
    - Break down complex components into smaller, reusable modules.
    - Keep components focused on a single responsibility.
    - Utilize shared utility functions and constants to avoid code duplication.  Create a `utils` directory for helper functions.
    - Use `components` directory to store UI components.

- **Component Architecture:**
    - Favor composition over inheritance. Create flexible components that can be customized through props.
    - Design components with clear separation of concerns: presentational components (UI) and container components (logic).
    - Use functional components with hooks for managing state and side effects.

- **Code Splitting Strategies:**
    - Implement lazy loading for non-critical components to improve initial load time.
    - Utilize React.lazy and Suspense for code splitting at the component level.
    - Configure your bundler (e.g., Webpack, Parcel) to automatically split code into smaller chunks.
    - Consider route-based code splitting for larger applications.

## 2. Common Patterns and Anti-patterns

- **Design Patterns Specific to Shadcn UI:**
    - Leverage the existing components provided by Shadcn UI whenever possible.
    - Customize components using styling solutions like Tailwind CSS's utility classes or CSS variables.
    - Create compound components by combining existing Shadcn UI components to build more complex UI elements.

- **Recommended Approaches for Common Tasks:**
    - Use Shadcn UI's form components (e.g., `Input`, `Select`) for handling user input.
    - Implement accessible components by following ARIA guidelines and using appropriate HTML semantics.
    - Use the `cn` utility (classnames library) provided by Shadcn UI to manage CSS class names effectively.

- **Anti-patterns and Code Smells to Avoid:**
    - Directly modifying the Shadcn UI component code.
    - Overusing custom CSS, as Shadcn UI is built with Tailwind CSS.
    - Neglecting accessibility considerations.
    - Creating overly complex components with too many responsibilities.

- **State Management Best Practices:**
    - Use React's built-in `useState` hook for simple component-level state.
    - Consider using a state management library like Zustand, Redux, or Recoil for more complex application state.
    - Avoid mutating state directly; always use the setState function or a state management library's update methods.

- **Error Handling Patterns:**
    - Implement error boundaries to catch errors in components and prevent the entire application from crashing.
    - Use try-catch blocks to handle errors in asynchronous operations and API calls.
    - Provide informative error messages to users.
    - Log errors to a monitoring service for debugging and analysis.

## 3. Performance Considerations

- **Optimization Techniques:**
    - Minimize re-renders by using `React.memo` for functional components and `shouldComponentUpdate` for class components.
    - Optimize event handlers by using useCallback to prevent unnecessary re-creation of functions.
    - Debounce or throttle expensive operations to reduce the frequency of execution.

- **Memory Management:**
    - Avoid memory leaks by properly cleaning up event listeners and timers in the `useEffect` hook.
    - Release unused resources, such as large data structures, when they are no longer needed.

- **Rendering Optimization:**
    - Use virtualized lists or grids for rendering large datasets.
    - Batch DOM updates to minimize reflows and repaints.
    - Use CSS containment to isolate rendering changes to specific parts of the DOM.

- **Bundle Size Optimization:**
    - Remove unused code and dependencies using tree shaking.
    - Minify JavaScript and CSS files to reduce their size.
    - Compress images using tools like ImageOptim or TinyPNG.

- **Lazy Loading Strategies:**
    - Implement lazy loading for images and other media assets.
    - Use the Intersection Observer API to detect when elements are visible in the viewport and load them on demand.

## 4. Security Best Practices

- **Common Vulnerabilities and How to Prevent Them:**
    - Prevent cross-site scripting (XSS) attacks by sanitizing user input and escaping HTML entities.
    - Protect against cross-site request forgery (CSRF) attacks by using anti-CSRF tokens.
    - Avoid storing sensitive information, such as API keys or passwords, in client-side code.

- **Input Validation:**
    - Validate user input on both the client-side and server-side.
    - Use a validation library like Zod or Yup to define data schemas and enforce validation rules.
    - Sanitize user input to remove potentially harmful characters or code.

- **Authentication and Authorization Patterns:**
    - Use a secure authentication protocol, such as OAuth 2.0 or OpenID Connect.
    - Implement role-based access control (RBAC) to restrict access to sensitive resources.
    - Store user credentials securely using hashing and salting.

- **Data Protection Strategies:**
    - Encrypt sensitive data at rest and in transit.
    - Use HTTPS to protect data transmitted between the client and server.
    - Implement data masking to hide sensitive information from unauthorized users.

- **Secure API Communication:**
    - Use HTTPS for all API requests.
    - Implement rate limiting to prevent abuse and denial-of-service attacks.
    - Validate API responses to ensure data integrity.

## 5. Testing Approaches

- **Unit Testing Strategies:**
    - Write unit tests for individual components and functions.
    - Use a testing framework like Jest or Mocha.
    - Test component behavior with different props and inputs.

- **Integration Testing:**
    - Write integration tests to verify that components work together correctly.
    - Test the interaction between components and APIs.

- **End-to-End Testing:**
    - Write end-to-end tests to simulate user interactions and verify that the application functions as expected.
    - Use a testing framework like Cypress or Playwright.

- **Test Organization:**
    - Organize tests into separate files based on the component or feature being tested.
    - Use descriptive test names that clearly indicate the purpose of the test.

- **Mocking and Stubbing:**
    - Use mocking and stubbing to isolate components and functions during testing.
    - Mock external dependencies, such as APIs or third-party libraries.

## 6. Common Pitfalls and Gotchas

- **Frequent Mistakes Developers Make:**
    - Forgetting to handle edge cases.
    - Overcomplicating components.
    - Neglecting accessibility.
    - Ignoring performance considerations.

- **Edge Cases to Be Aware Of:**
    - Handling different screen sizes and devices.
    - Dealing with slow network connections.
    - Handling invalid or unexpected user input.

- **Version-Specific Issues:**
    - Be aware of breaking changes between Shadcn UI versions.
    - Consult the Shadcn UI changelog for migration instructions.

- **Compatibility Concerns:**
    - Ensure that your application is compatible with the target browsers and devices.
    - Test your application on different browsers and devices.

- **Debugging Strategies:**
    - Use browser developer tools to inspect the DOM and debug JavaScript code.
    - Use console logging to track the flow of execution and identify errors.
    - Use a debugger to step through code and inspect variables.

## 7. Tooling and Environment

- **Recommended Development Tools:**
    - Visual Studio Code (VS Code) with extensions for React, TypeScript, and Tailwind CSS.
    - A browser with developer tools (e.g., Chrome DevTools, Firefox Developer Tools).
    - A terminal for running commands and scripts.

- **Build Configuration:**
    - Use a build tool like Webpack, Parcel, or Rollup to bundle your application.
    - Configure your build tool to optimize code for production.

- **Linting and Formatting:**
    - Use ESLint to enforce code style and identify potential errors.
    - Use Prettier to automatically format code.
    - Configure your editor to automatically lint and format code on save.

- **Deployment Best Practices:**
    - Deploy your application to a reliable hosting provider.
    - Use a content delivery network (CDN) to serve static assets.
    - Configure your server to serve compressed files.

- **CI/CD Integration:**
    - Use a continuous integration and continuous deployment (CI/CD) pipeline to automate the build, test, and deployment process.
    - Integrate your CI/CD pipeline with your version control system.