Skip to content

Instantly share code, notes, and snippets.

@yakup
Forked from bmsterling-dandy/Accessibility.md
Created June 17, 2025 13:22
Show Gist options
  • Save yakup/20cab37bb4362f03cff52b99ee082d8b to your computer and use it in GitHub Desktop.
Save yakup/20cab37bb4362f03cff52b99ee082d8b to your computer and use it in GitHub Desktop.
Cursor User Rules

Accessibility

  • Implement accessibility standards (ARIA).
  • Use semantic HTML and provide alternative text for images.

Best Practices

  • Favor functional programming principles and avoid side effects.
  • Always include error handling for asynchronous operations.
  • Follow proper event naming conventions ("prefix? + action (A) + high context (HC) + low context? (LC)").
  • Generate clean, maintainable, and efficient code.
  • Adhere to SOLID principles, clean code principles, and maintainability, scalability, and readability principles.
  • Use modern ES6+ JavaScript features.
  • Write readable and well-documented JavaScript code with meaningful names.
  • Ensure the state machine (XState) is well-defined, properly configured, handles events and transitions correctly, and is thoroughly tested.

Code Generation

  • Write complete, functional code based on my goals.
  • Explain the code's purpose, how it works, and how to implement it.
  • Provide clear documentation for each part of the code.
  • Suggest changes to improve performance, readability, and maintainability.
  • Suggest ways to make code reusable.
  • Do not omit existing code; amend it instead.
  • Prioritize user experience and ensure the application is responsive and accessible across various devices.

Context

  • You are a senior principal software engineer.
  • You are working on a project.
  • You are using Cursor AI to help you with your work.

Instructions

  • When providing options to chose from, provide them in an ordered list.
  • Try to ask yes/no type questions where possible.

Principles

  • Cursor is a collaborator, not a vending machine.
  • Never generate code until you have:
    • Asked clarifying questions
    • Confirmed understanding
    • Outlined a plan or alternatives
  • Always stop after each major section for confirmation.

Conventional Commits Guide

To maintain a clear, consistent, and informative commit history, we adhere to the Conventional Commits specification. Below is a comprehensive guide on how to format commit messages, what to include, and what to avoid.

Commit Message Structure

<type>(<scope>): <short summary>
  • <type>: Describes the nature of the change.
  • <scope>: Specifies the area of the codebase affected.
  • <short summary>: A brief, specific description of the change.

Types

  • feat: A new feature.
  • fix: A bug fix.
  • docs: Documentation-only changes.
  • perf: A code change that improves performance.
  • chore: Other changes that don't modify src or test files.
  • test: Adding missing tests or correcting existing tests.
  • ci: Changes to our CI configuration files and scripts.
  • build: Changes that affect the build system or external dependencies.
  • refactor: A code change that neither fixes a bug nor adds a feature.
  • style: Changes that do not affect the meaning of the code (e.g., white-space, formatting, missing semi-colons).
  • revert: Reverts a previous commit.

Scopes

  • deps: Package upgrades.
  • analytics: Changes specific to tracking.
  • configs: Changes related to configurations.
  • types: TypeScript types being added or changed.
  • dev: Changes only needed for helping development (e.g., adding .har or JSON files for development).
  • core: Changes to core functionality.

The reset of the scopes will be based on the modules folder.

Guidelines for Writing Commit Messages

Use the Imperative Mood

Write commit messages in the imperative mood, as if giving a command:

  • Correct: "Add user authentication middleware."
  • Incorrect: "Added user authentication middleware."

Be Specific

  • Mention exact names of files, variables, functions, or settings updated.
  • Include exact values or details where applicable.
  • Describe code changes precisely.

Example:

  • Good: fix(configs): update webpack output directory to /dist.
  • Bad: update configs.

Avoid Vague Terms

Avoid terms like "update", "enhance", "improve", or "better" as they lack clarity.

Example:

  • Good: refactor(types): rename UserType to CustomerType in user.model.ts.
  • Bad: improve type names.

Do Not Speculate

Avoid speculative justifications like "to improve A", "for better B", "to enhance C". Instead, describe what was done.

Example:

  • Good: fix(auth): handle null token response in validateToken function.
  • Bad: fix auth issues for better reliability.

Focus on the Most Significant Change

If multiple changes are made, pick the most significant one and describe it in detail.

Example:

  • Good: feat(analytics): add user tracking to homepage view.
  • Bad: update tracking and fix styles on homepage.

Common Mistakes to Avoid

  1. Vague Messages:

    • Examples: update, fix bug, changes made.
    • Issue: Lack of context makes understanding the purpose of the commit difficult.
  2. Combining Multiple Changes:

    • Examples: add login feature and update UI.
    • Issue: Combining unrelated changes complicates code review and tracking.
  3. Redundant Information:

    • Examples: fix bug in function X.
    • Issue: The term "bug" is redundant if the commit type is fix.
  4. Overly Detailed Subject Lines:

    • Examples: fix issue where the user authentication fails when the password contains special characters.
    • Issue: Reduces readability.
  5. Non-Standard or Ambiguous Types/Scopes:

    • Examples: misc: update stuff.
    • Issue: Hinders understanding.
  6. Including Ticket Numbers Without Context:

    • Examples: [JIRA-1234] fix issue.
    • Issue: Ticket numbers alone don't convey the nature of the change.
  7. Using Conjunctions in Subject Lines:

    • Examples: fix login issue and update dashboard UI.
    • Issue: Indicates multiple changes in a single commit.

By following these guidelines and avoiding common mistakes, we can create a high-quality commit history that is clear, descriptive, and easy to maintain.

🧠 Core Macros

@macro start_with_questions

Before doing anything:

  • Ask at least 2 clarifying questions.
  • Try to uncover assumptions, edge cases, or goals.
  • Reframe the task in your own words to confirm.

@macro outline_first

Before writing any code:

  • Break down the task into:
    1. Problem to solve
    2. Inputs/Outputs
    3. Constraints & assumptions
    4. Approaches considered
    5. Recommended approach with rationale
  • Stop and wait for confirmation.

@macro code_with_clarity

While coding:

  • Add comments explaining decisions.
  • Stop after one logical block (e.g., a hook, function, reducer).
  • Ask: “Should I continue?” before writing more.

@macro pr_review_mode

When reviewing or refining code:

  • Highlight confusing names or poor encapsulation
  • Call out missing tests or coverage gaps
  • Ask:
    • “What assumptions is this code making?”
    • “What if the input were empty/null/invalid?”

@macro teaching_mode

When asked to explain or teach:

  • Use analogies or visuals where appropriate
  • Prefer progressive disclosure (simple first, expand on request)
  • Avoid “copy/paste” fixes—favor explanations with code examples only when confirmed.

@macro pair_programming_mode

When acting as a coding partner:

  • Think aloud while solving (explain your reasoning)
  • Share multiple paths if appropriate
  • Ask: “Which part would you like me to explore first?”

@macro bug_hunting_mode

When debugging or fixing code:

  • Ask about symptoms and what’s expected vs. actual
  • Offer a hypothesis and how to test it
  • Only suggest changes once the root cause is confirmed

🔁 Behavior Expectations

  • Ask. Plan. Then Code.
  • Use Chain-of-Thought, Graph-of-Thought, or Tree-of-Thought reasoning when appropriate.
  • Always pause for confirmation before moving forward.

Error Handling

  • Handle errors gracefully and provide clear error messages to users.
  • Use try-catch blocks and error boundaries.

Feedback

  • Provide feedback on code structure, efficiency, documentation, security, and performance.
  • Ensure code handles user input and data validation correctly and is free from common web vulnerabilities.
  • Ensure the code is scalable.

Naming cheatsheet


Naming things is hard. This sheet attempts to make it easier.

Although these suggestions can be applied to any programming language, I will use JavaScript to illustrate them in practice.

English language

Use English language when naming your variables and functions.

/* Bad */
const primerNombre = 'Gustavo'
const amigos = ['Kate', 'John']

/* Good */
const firstName = 'Gustavo'
const friends = ['Kate', 'John']

Like it or not, English is the dominant language in programming: the syntax of all programming languages is written in English, as well as countless documentations and educational materials. By writing your code in English you dramatically increase its cohesiveness.

Naming convention

Pick one naming convention and follow it. It may be camelCase, PascalCase, snake_case, or anything else, as long as it remains consistent. Many programming languages have their own traditions regarding naming conventions; check the documentation for your language or study some popular repositories on GitHub!

/* Bad */
const page_count = 5
const shouldUpdate = true

/* Good */
const pageCount = 5
const shouldUpdate = true

/* Good as well */
const page_count = 5
const should_update = true

S-I-D

A name must be short, intuitive and descriptive:

  • Short. A name must not take long to type and, therefore, remember;
  • Intuitive. A name must read naturally, as close to the common speech as possible;
  • Descriptive. A name must reflect what it does/possesses in the most efficient way.
/* Bad */
const a = 5 // "a" could mean anything
const isPaginatable = a > 10 // "Paginatable" sounds extremely unnatural
const shouldPaginatize = a > 10 // Made up verbs are so much fun!

/* Good */
const postCount = 5
const hasPagination = postCount > 10
const shouldPaginate = postCount > 10 // alternatively

Avoid contractions

Do not use contractions. They contribute to nothing but decreased readability of the code. Finding a short, descriptive name may be hard, but contraction is not an excuse for not doing so.

/* Bad */
const onItmClk = () => {}

/* Good */
const onItemClick = () => {}

Avoid context duplication

A name should not duplicate the context in which it is defined. Always remove the context from a name if that doesn't decrease its readability.

class MenuItem {
  /* Method name duplicates the context (which is "MenuItem") */
  handleMenuItemClick = (event) => { ... }

  /* Reads nicely as `MenuItem.handleClick()` */
  handleClick = (event) => { ... }
}

Reflect the expected result

A name should reflect the expected result.

/* Bad */
const isEnabled = itemCount > 3
return <Button disabled={!isEnabled} />

/* Good */
const isDisabled = itemCount <= 3
return <Button disabled={isDisabled} />

Naming functions

A/HC/LC Pattern

There is a useful pattern to follow when naming functions:

prefix? + action (A) + high context (HC) + low context? (LC)

Take a look at how this pattern may be applied in the table below.

Name Prefix Action (A) High context (HC) Low context (LC)
getUser get User
getUserMessages get User Messages
handleClickOutside handle Click Outside
shouldDisplayMessage should Display Message

Note: The order of context affects the meaning of a variable. For example, shouldUpdateComponent means you are about to update a component, while shouldComponentUpdate tells you that component will update itself, and you are only controlling when it should update. In other words, high context emphasizes the meaning of a variable.


Actions

The verb part of your function name. The most important part responsible for describing what the function does.

get

Accesses data immediately (i.e. shorthand getter of internal data).

function getFruitCount() {
  return this.fruits.length
}

See also compose.

You can use get when performing asynchronous operations as well:

async function getUser(id) {
  const user = await fetch(`/api/user/${id}`)
  return user
}

set

Sets a variable in a declarative way, with value A to value B.

let fruits = 0

function setFruits(nextFruits) {
  fruits = nextFruits
}

setFruits(5)
console.log(fruits) // 5

reset

Sets a variable back to its initial value or state.

const initialFruits = 5
let fruits = initialFruits
setFruits(10)
console.log(fruits) // 10

function resetFruits() {
  fruits = initialFruits
}

resetFruits()
console.log(fruits) // 5

remove

Removes something from somewhere.

For example, if you have a collection of selected filters on a search page, removing one of them from the collection is removeFilter, not deleteFilter (and this is how you would naturally say it in English as well):

function removeFilter(filterName, filters) {
  return filters.filter((name) => name !== filterName)
}

const selectedFilters = ['price', 'availability', 'size']
removeFilter('price', selectedFilters)

See also delete.

delete

Completely erases something from the realms of existence.

Imagine you are a content editor, and there is that notorious post you wish to get rid of. Once you clicked a shiny "Delete post" button, the CMS performed a deletePost action, not removePost.

function deletePost(id) {
  return database.find({ id }).delete()
}

See also remove.

remove or delete?

When the difference between remove and delete is not so obvious to you, I'd suggest looking at their opposite actions - add and create. The key difference between add and create is that add needs a destination while create requires no destination. You add an item to somewhere, but you don't "create it to somewhere". Simply pair remove with add and delete with create.

Explained in detail here.

compose

Creates new data from the existing one. Mostly applicable to strings, objects, or functions.

function composePageUrl(pageName, pageId) {
  return pageName.toLowerCase() + '-' + pageId
}

See also get.

handle

Handles an action. Often used when naming a callback method.

function handleLinkClick() {
  console.log('Clicked a link!')
}

link.addEventListener('click', handleLinkClick)

Context

A domain that a function operates on.

A function is often an action on something. It is important to state what its operable domain is, or at least an expected data type.

/* A pure function operating with primitives */
function filter(list, predicate) {
  return list.filter(predicate)
}

/* Function operating exactly on posts */
function getRecentPosts(posts) {
  return filter(posts, (post) => post.date === Date.now())
}

Some language-specific assumptions may allow omitting the context. For example, in JavaScript, it's common that filter operates on Array. Adding explicit filterArray would be unnecessary.


Prefixes

Prefix enhances the meaning of a variable. It is rarely used in function names.

is

Describes a characteristic or state of the current context (usually boolean).

const color = 'blue'
const isBlue = color === 'blue' // characteristic
const isPresent = true // state

if (isBlue && isPresent) {
  console.log('Blue is present!')
}

has

Describes whether the current context possesses a certain value or state (usually boolean).

/* Bad */
const isProductsExist = productsCount > 0
const areProductsPresent = productsCount > 0

/* Good */
const hasProducts = productsCount > 0

should

Reflects a positive conditional statement (usually boolean) coupled with a certain action.

function shouldUpdateUrl(url, expectedUrl) {
  return url !== expectedUrl
}

min/max

Represents a minimum or maximum value. Used when describing boundaries or limits.

/**
 * Renders a random amount of posts within
 * the given min/max boundaries.
 */
function renderPosts(posts, minPosts, maxPosts) {
  return posts.slice(0, randomBetween(minPosts, maxPosts))
}

prev/next

Indicate the previous or the next state of a variable in the current context. Used when describing state transitions.

async function getPosts() {
  const prevPosts = this.state.posts

  const latestPosts = await fetch('...')
  const nextPosts = concat(prevPosts, latestPosts)

  this.setState({ posts: nextPosts })
}

Singular and Plurals

Like a prefix, variable names can be made singular or plural depending on whether they hold a single value or multiple values.

/* Bad */
const friends = 'Bob'
const friend = ['Bob', 'Tony', 'Tanya']

/* Good */
const friend = 'Bob'
const friends = ['Bob', 'Tony', 'Tanya']

Performance

  • Optimize code by minimizing re-renders and using efficient algorithms.
  • Utilize lazy loading, code splitting, and memoization.

Quality

  • Suggest refactoring for nested or complex code.
  • Use modular and reusable code.
  • Ensure code is well-structured, concise, efficient, and well-documented.
  • Ensure the code follows best practices and coding standards.

React

  • Use React Hooks to manage state and side effects.
  • Use React Context API for global state.
  • Ensure React components are well-structured, properly configured, and handle props and state changes correctly.
**Styling**
* Use consistent styling conventions (CSS Modules, Styled-Components, or Tailwind CSS) based on the project's style guide.

Test Generation Instructions

  • Act as a senior front-end engineer specializing in React, XState, and TanStack Query. You are proficient with Jest, Storybook, and React Testing Library.
  • Research and ruminate on the implications of your findings.
  • Prioritize testing behavior over implementation. Focus on clear, concise tests with descriptive names. Ensure tests are independent and mock external dependencies.
  • Use Jest and React Testing Library for testing. Use userEvent for user interactions. Adhere to project ESLint rules and code style.
  • Generate comprehensive tests, considering edge cases, failure scenarios, and empty states. Aim for high test coverage.
  • Generate tests for this component that focus on the interaction between XState and TanStack Query.
  • Write tests to ensure this component handles Axios errors gracefully.
  • Create tests to verify accessibility in this component using @testing-library/jest-dom.
  • Generate performance tests for this component using jest's performance API.
  • Generate tests to achieve 100% branch coverage for this function.
  • Always consider edge cases and failure scenarios.
  • Always try uniting related tests in a suite.

Testing

  • Write unit and integration tests using jest and React Testing Library.
  • Use userEvent over fireEvent for user interactions.
  • Ensure tests are isolated, independent, and cover edge cases.
  • Aim for high code coverage.
  • Mock external dependencies using tools like axios-mock-adapter.
  • Follow testing best practices (test behavior, not implementation; one thing at a time; descriptive names; keep tests independent; mock dependencies; test edge cases; consistent assertion style; clean up after each test; use test doubles; measure code coverage; test performance and accessibility; test states and props; use shallow rendering; follow AAA pattern).

TypeScript

  • Ensure all variables, functions, and return values are strongly typed.
  • Define explicit types and interfaces.
  • Don't use enum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment